如果我这样做:
const char* StringPtr = "string0"
,
那肯定是在记忆中的某个地方,我可以得到StringPtr
的地址。
但如果我这样做:
#define STRING0 "string0"
,那么STRING0
所在的位置是什么?
或者,STRING0
是否存在于内存中,因为编译器会替换STRING0
使用"string0"
?
据我所知,无论何时在代码中编写任何字符串,编译器都必须将其放在内存中,但我不知道它的确切行为。
但我对此并不十分肯定。
有人可以解释编译器是如何操纵#define
编辑或声明为char*
的字符串的?
另外,哪一个更好?字符串头文件中的#define
,extern const char*
或extern const std::string
?
谢谢!
答案 0 :(得分:5)
在几乎所有情况下,都允许编译器将字符串文字放在任何需要的位置。每次文字出现在源代码中时可能有一个副本,或者在实例之间共享一个主副本。
这会在C中引起麻烦,其中const
并不意味着相同的事情,您可以修改内存。在一个平台上,所有相同的字符串都会更改,而在另一个平台上,不会传播。从C ++ 11开始,字符串文字不会隐含地丢失const
,并且更难以犯错误。
字符串将在程序启动之前全部初始化,因此它们实际上是可执行二进制映像的一部分。这是肯定的。
这有什么不同:
const char StringPtr[] = "string0",
这定义了一个具有唯一地址的专用数组对象。
答案 1 :(得分:1)
#define STRING0
STRING0
不驻留在内存中。它在编译期间甚至不存在。在PRE编译中,STRING0
的所有出现都被preprocessor替换为“string0”。在此阶段之后,以下任何阶段或编译的应用程序都不知道名称STRING0
一旦发生这种情况,许多并非所有实例都会以代码中的唯一字符串文字(您的const char*
大小写)结束。 @Potatoswatter和@silico提供的link可以更好地回答这些存储在内存中的答案。
答案 2 :(得分:1)
stringPtr驻留在可执行文件的数据部分中。如果您在文本编辑器中打开您的exe,您将能够搜索它。 Data Segment
宏仅在构建程序的预处理阶段持续存在。
根据您的编译器,如果您使用宏方法,您最终可能会在exe中使用相同字符串的几个单独实例,但如果使用char *方法,则只能使用单个实例。
答案 3 :(得分:0)
#define
是预处理器宏。在编译代码之前,它将在预编译阶段用STRING0
替换"string0"
。
"string0"
驻留在可执行文件的静态只读内存中。
StringPtr
是一个变量,这就是你可以获取其地址的原因。它只是指向"string0"
的内存地址。
答案 4 :(得分:-1)
当您执行#define
时,没有编译器,但预处理器在预先替换为文本“STRING0
”中的“string0”处理后的源文件,然后再将其传递给编译器。
编译器从不看到STRING0,但只看到你编写STRING0的“string0”。
编辑:
替换您在源文件中编写的STRING0的每个“string0”实例本身就是字符串文字。如果这些字符串文字保证(或声明)为不变,则编译器可能通过存储这种“string0”和点其它用途实现这一拷贝的单个拷贝优化存储器分配(I改写在编辑本段)。
(编辑:那些相同的文字字符串常量可能会合并为单个副本,但这取决于编译器。标准不要求或强制执行它:http://www.velocityreviews.com/forums/t946521-merging-of-string-literals-guaranteed-by-c-std.html)
至于你的上一个问题:最便携的是将它们声明为:const char *
稍后编辑:到目前为止我找到的关于字符串文字的最佳讨论是:https://stackoverflow.com/a/2245983/1284631
另外,请注意字符串文字也可以出现在静态分配的char数组的初始化中,因为它不能与其它副本合并,因为静态数组的内容可能会被覆盖。请参阅下面的示例,其中两个相同的字符串文字“hello”无法合并:
#include <stdio.h>
#include <string.h>
int main(){
char x[50]="hello";
printf("x=%s, &x[0]=%p\n",x,&x[0]);
const char *y="hello";
printf("y=%s, &y[0]=%p\n",y,&y[0]);
strcpy(&x[0],"zz");
printf("x=%s, &x[0]=%p\n",x,&x[0]);
return 0;
}
此代码的输出为:
x=hello, &x[0]=0x7fff8a964370
y=hello, &y[0]=0x400714
x=zz, &x[0]=0x7fff8a964370