免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
123下一页
最近访问板块 发新帖
查看: 5810 | 回复: 21
打印 上一主题 下一主题

字符串字面值的问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-05-12 23:26 |只看该作者 |倒序浏览
1. in C++, a string literal has type "const char[]" with static storage duration
但是
const char str[] = "asdfasdf";
char *p = str;
会有错,而
char *p2 = "asdfasdf";
则可以编译,尽管修改p2会段错误。why?

2. in C, a string literal has type " char[]" with static storage duration
那么
{
char *p = "asdfasdf";
char *p2[] = "asdfasdf";
char *p3 = (char[]){"asdfasdf"};
}
都不同。第一个在栈上有一个指针,指向某个只读串(通常在只读页里的)。
第二个在栈上有个字符串,第三个在栈上有个指针指向栈上的一个字符串(无名的,可修改)。
那么对于后两种情形,是否一定有个static storage duration的只读串用于初始化栈呢?
或者说对于后两种情形,可否仅在函数里hard code这个串呢?毕竟那个string literal已经无法访问到了!

论坛徽章:
0
2 [报告]
发表于 2007-05-12 23:35 |只看该作者
原帖由 delimy 于 2007-5-12 23:26 发表
1. in C++, a string literal has type "const char[]" with static storage duration
但是
const char str[] = "asdfasdf";
char *p = str;会有错,而
char *p2 = "asdfasdf";
则可以编译,尽管修改p2会段错误。why?
这个应该算是个例外,The c++上有说明。
2. in C, a string literal has type " char[]" with static storage duration
那么
{
char *p = "asdfasdf";
char *p2[] = "asdfasdf";
char *p3 = (char[]){"asdfasdf"};
}
都不同。第一个在栈上有一个指针,指向某个只读串(通常在只读页里的)。
第二个在栈上有个字符串,第三个在栈上有个指针指向栈上的一个字符串(无名的,可修改)。
那么对于后两种情形,是否一定有个static storage duration的只读串用于初始化栈呢?或者说对于后两种情形,可否仅在函数里hard code这个串呢?毕竟那个string literal已经无法访问到了!

要的,理由很简单,这个串的地址在栈中,要到运行时才知道地址,知道要放哪,也就是当前栈上。这需要一个显示的copy动作。

论坛徽章:
0
3 [报告]
发表于 2007-05-12 23:36 |只看该作者
是否一定有个static storage duration的只读串用于初始化栈呢?

当然,还有一些体系结构没有栈,不过我不了解这个。

论坛徽章:
0
4 [报告]
发表于 2007-05-12 23:43 |只看该作者
原帖由 delimy 于 2007-5-12 23:26 发表
1. in C++, a string literal has type "const char[]" with static storage duration
但是
char *p2 = "asdfasdf";
则可以编译,


为了和旧代码兼容

论坛徽章:
95
程序设计版块每日发帖之星
日期:2015-09-05 06:20:00程序设计版块每日发帖之星
日期:2015-09-17 06:20:00程序设计版块每日发帖之星
日期:2015-09-18 06:20:002015亚冠之阿尔艾因
日期:2015-09-18 10:35:08月度论坛发贴之星
日期:2015-09-30 22:25:002015亚冠之阿尔沙巴布
日期:2015-10-03 08:57:39程序设计版块每日发帖之星
日期:2015-10-05 06:20:00每日论坛发贴之星
日期:2015-10-05 06:20:002015年亚冠纪念徽章
日期:2015-10-06 10:06:482015亚冠之塔什干棉农
日期:2015-10-19 19:43:35程序设计版块每日发帖之星
日期:2015-10-21 06:20:00每日论坛发贴之星
日期:2015-09-14 06:20:00
5 [报告]
发表于 2007-05-12 23:52 |只看该作者

  1. char p[] = "abcd";
  2. char *p1 = (char []){"abcd"};
复制代码

这两个定义其实是差不多的。如果它们在函数中出现,那么 p 和 p1 指向的地址都在栈上分配。

第二个定义的详情可参见 C99 6.5.2.5 Compound literals

论坛徽章:
0
6 [报告]
发表于 2007-05-13 08:52 |只看该作者
原帖由 MMMIX 于 2007-5-12 23:52 发表

  1. char p[] = "abcd";
  2. char *p1 = (char []){"abcd"};
复制代码

这两个定义其实是差不多的。如果它们在函数中出现,那么 p 和 p1 指向的地址都在栈上分配

第二个定义的详情可参见 C99 6.5.2.5 Compound literals  


如果我指定 register 存储类呢?

.

论坛徽章:
0
7 [报告]
发表于 2007-05-13 09:28 |只看该作者
原帖由 langue 于 2007-5-13 08:52 发表


如果我指定 register 存储类呢?

.

那编译器可能将指针 p 和 p1 放到寄存器上,但 "abcd" 不会在寄存器上。

论坛徽章:
0
8 [报告]
发表于 2007-05-13 09:43 |只看该作者
原帖由 antigloss 于 2007-5-13 09:28 发表

那编译器可能将指针 p 和 p1 放到寄存器上,但 "abcd" 不会在寄存器上。

  1. $ objdump -S register.o

  2. register.o:     file format elf32-i386

  3. Disassembly of section .text:

  4. 00000000 <main>:
  5. #include <stdio.h>

  6. int
  7. main()
  8. {
  9.    0:   55                      push   %ebp
  10.    1:   89 e5                   mov    %esp,%ebp
  11.    3:   83 ec 18                sub    $0x18,%esp
  12.    6:   83 e4 f0                and    $0xfffffff0,%esp
  13.    9:   b8 00 00 00 00          mov    $0x0,%eax
  14.    e:   29 c4                   sub    %eax,%esp
  15.   10:   a1 00 00 00 00          mov    0x0,%eax
  16.   15:   89 45 e8                mov    %eax,0xffffffe8(%ebp)
  17.     register char a[4] = {0, 1, 2, 3};
  18.   18:   b8 00 00 00 00          mov    $0x0,%eax
  19.   1d:   ba 01 00 00 00          mov    $0x1,%edx
  20.   22:   88 d4                   mov    %dl,%ah
  21.   24:   25 ff ff 00 ff          and    $0xff00ffff,%eax
  22.   29:   0d 00 00 02 00          or     $0x20000,%eax
  23.   2e:   25 ff ff ff 00          and    $0xffffff,%eax
  24.   33:   0d 00 00 00 03          or     $0x3000000,%eax

  25.     a[0]=0;
  26.   38:   b0 00                   mov    $0x0,%al
  27.     a[1]=1;
  28.   3a:   ba 01 00 00 00          mov    $0x1,%edx
  29.   3f:   88 d4                   mov    %dl,%ah
  30.     a[2]=2;
  31.   41:   25 ff ff 00 ff          and    $0xff00ffff,%eax
  32.   46:   0d 00 00 02 00          or     $0x20000,%eax
  33.     a[3]=3;
  34.   4b:   25 ff ff ff 00          and    $0xffffff,%eax
  35.   50:   0d 00 00 00 03          or     $0x3000000,%eax

  36.     printf("%d\n%d\n%d\n%d\n", a[0], a[1], a[2], a[3]);
  37.   55:   83 ec 0c                sub    $0xc,%esp
  38.   58:   89 c2                   mov    %eax,%edx
  39.   5a:   c1 fa 18                sar    $0x18,%edx
  40.   5d:   0f be d2                movsbl %dl,%edx
  41.   60:   52                      push   %edx
  42.   61:   89 c2                   mov    %eax,%edx
  43.   63:   c1 e2 08                shl    $0x8,%edx
  44.   66:   c1 fa 18                sar    $0x18,%edx
  45.   69:   0f be d2                movsbl %dl,%edx
  46.   6c:   52                      push   %edx
  47.   6d:   0f be d4                movsbl %ah,%edx
  48.   70:   0f be d2                movsbl %dl,%edx
  49.   73:   52                      push   %edx
  50.   74:   0f be c0                movsbl %al,%eax
  51.   77:   50                      push   %eax
  52.   78:   68 00 00 00 00          push   $0x0
  53.   7d:   e8 fc ff ff ff          call   7e <main+0x7e>
  54.   82:   83 c4 20                add    $0x20,%esp

  55.     return 0;
  56.   85:   b8 00 00 00 00          mov    $0x0,%eax
  57. }
  58.   8a:   8b 55 e8                mov    0xffffffe8(%ebp),%edx
  59.   8d:   3b 15 00 00 00 00       cmp    0x0,%edx
  60.   93:   74 13                   je     a8 <main+0xa8>
  61.   95:   83 ec 08                sub    $0x8,%esp
  62.   98:   ff 75 e8                pushl  0xffffffe8(%ebp)
  63.   9b:   68 0d 00 00 00          push   $0xd
  64.   a0:   e8 fc ff ff ff          call   a1 <main+0xa1>
  65.   a5:   83 c4 10                add    $0x10,%esp
  66.   a8:   c9                      leave
  67.   a9:   c3                      ret
  68. $
复制代码


其实我不该拿汇编代码出来

.

论坛徽章:
0
9 [报告]
发表于 2007-05-13 12:59 |只看该作者
原帖由 antigloss 于 2007-5-12 23:43 发表


为了和旧代码兼容

比较想知道这个兼容在C++标准哪一节规定的

论坛徽章:
0
10 [报告]
发表于 2007-05-13 13:04 |只看该作者
原帖由 MMMIX 于 2007-5-12 23:52 发表

  1. char p[] = "abcd";
  2. char *p1 = (char []){"abcd"};
复制代码

这两个定义其实是差不多的。如果它们在函数中出现,那么 p 和 p1 指向的地址都在栈上分配。

第二个定义的详情可参 ...

不一样的吧。p是数组,不是指针。p在栈上分配,并且通过copy的方式初始化。
p1是指针,初始化为一个匿名物体(一个数组)的地址,那个匿名数组如上情形。
后一种在栈上多了个指针。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP