【发布时间】:2018-06-19 22:59:10
【问题描述】:
据我了解,以下代码的工作方式如下:
char* cptr = "Hello World";
“Hello World”位于程序内存的.rodata 部分。字符串字面量"Hello World" 返回一个指向字符串基地址的指针,或者所谓的“数组”中第一个元素的地址,因为字符在内存中按顺序排列,所以它是“H”。这是我的小图,因为我可视化了存储在内存中的字符串文字:
0x4 : 'H'
0x5 : 'e'
0x6 : 'l'
0x6 : 'l'
0x7 : 'o'
0x8 : ' '
0x9 : 'W'
0xa : 'o'
0xb : 'r'
0xc : 'l'
0xd : 'd'
0xe : '\0'
所以上面的声明变成了:
char* cptr = 0x4;
现在 cptr 指向字符串文字。我只是在编地址。
0xa1 : 0x4
现在这段代码是如何工作的?
char cString[] = "Hello World";
我假设和之前的情况一样,"Hello World" 也降级为 'H' 和 0x4 的地址。
char cString[] = 0x4;
当 = 与 char 数组的初始化一起使用时,我将其作为重载赋值运算符阅读。据我了解,仅在初始化 C 字符串时,它会从给定的基地址开始逐个字符地复制到 C 字符串中,直到它作为最后一个复制的字符命中 '\0' 为止。它还为所有字符分配足够的内存。因为重载的运算符实际上只是函数,所以我假设它的内部实现类似于strcpy()。
我希望一位更有经验的 C 程序员确认我对这段代码如何工作的假设。这是我在将字符串文字中的字符复制到其中之后对 C 字符串的可视化:
0xb4 : 'H'
0xb5 : 'e'
0xb6 : 'l'
0xb6 : 'l'
0xb7 : 'o'
0xb8 : ' '
0xb9 : 'W'
0xba : 'o'
0xbb : 'r'
0xbc : 'l'
0xbd : 'd'
0xbe : '\0'
再一次,地址是任意的,关键是堆栈中的 C 字符串与内存中 .rodata 部分中的字符串文字不同。
我想做什么?我正在尝试使用 char 指针来临时保存字符串文字的基地址,并使用相同的 char 指针(字符串文字的基地址)来初始化 C 字符串。
char* cptr = "Hello World";
char cString[] = cptr;
我假设"Hello World" 的计算结果是它的基地址0x4。所以这段代码应该是这样的:
char* cptr = 0x4;
char cString[] = 0x4;
我认为它应该与char cString[] = "Hello World"; 没有什么不同,因为“Hello World”的计算结果是它的基地址,这就是存储在 char 指针中的内容!
但是,gcc 给了我一个错误:
error: invalid initializer
char cString[] = cptr;
^
- 为什么不能使用 char 指针作为临时占位符来存储字符串文字的基地址?
- 此代码如何工作?我的假设是否正确?
- 在代码中使用字符串文字是否会将基地址返回到将字符存储在内存中的“数组”?
【问题讨论】:
-
数组不是指针。在 SO 和网络上的其他地方有很多很多对此的解释。是的,您可以分配一个指针,使其指向一个数组。不,您不能分配一个数组以使其指向任何东西(因为它不是指针)。初始化
char cString[] = "Hello World"不涉及任何指针——符号cString最终是一个 12 个字符的数组的地址,使用“Hello World”中的字符进行初始化。 -
你写“所谓的'数组'”好像有什么可疑之处。那没有。术语“数组”在 C 中定义良好,标准明确规定将 C 源文件翻译成程序的部分过程是在每个字符串字面量中添加一个空字节,并使用生成的字节序列来初始化静态数组的长度足以容纳它们。没有“好像”或“喜欢”——出现在 C 源代码中的字符串文字对应于程序中的 真正 数组。
-
我不懂“善意”。我的观点是字符串文字似乎是存储在程序的 .rodata 部分中的数组。但是,它不是一个数组,因为我,程序员,会在代码中显式声明它:char array[];
标签: c pointers literals c-strings