在here中,对于全局变量,可以使用以下形式:
(1) const char *a = "...";
不如:
(2) const char a[] = "..."
为什么呢?我一直认为(1)更好,因为(2)实际上复制了我们分配它的字符串,而(1)只指向它。
答案 0 :(得分:3)
livejournal链接的参数是(1)通过创建单独的指针变量和安全漏洞引入了不必要的间接级别,因为指针变量可能被覆盖。假设以下两个声明:
char *p = "This is a test";
char s[] = "This is a test";
假设这些声明属于文件范围,因此p
和s
都具有静态范围。
这是一个假设的记忆图,显示了所有内容的布局:
0x00 0x01 0x02 0x03 0x00008000: 'T' 'h' 'i' 's' 0x00008004: ' ' 'i' 's' ' ' 0x00008008: 'a' ' ' 't' 'e' 0x0000800C: 's' 't' 0 ... ... p: 0x00010000: 0x00 0x00 0x80 0x00 s: 0x00010004: 'T' 'h' 'i' 's' 0x00010008: ' ' 'i' 's' ' ' 0x0001000C: 'a' ' ' 't' 'e' 0x00010010: 's' 't' 0 ...
链接中显示的参数如下:
p
是与其引用的字符串不同的对象;它本身不包含字符串值,而s
则包含; p
指向其他地方(可能是包含恶意代码的段),而您无法重新分配{{1 }}。 s
读取字符串,首先必须加载内容0x00010000获取字符串地址(0x00008000),然后您必须加载0x00008000的内容以获取字符串值本身。如果您正在执行 lot ,那么使用char数组并删除一个间接级别可能会导致显着的性能提升。 总之,您需要交换一点内存以提高速度和安全性。当然,这假设一个特定的操作环境,并且可能不适用于普遍的。
答案 1 :(得分:1)
在(2)中,字符串仅存在于一个版本中,并且您直接通过其地址对其进行操作。
在(1)内存中存在字符串,然后将此地址放在内存中的另一个位置,并强制自己每次需要时从其他位置读取地址。实际上,它增加了一个(无用的)间接。
编辑:
正如我在下面的评论中所说的那样,对于另一个答案,(2)中没有重复。
T.C:
char *p = "This is a test";
char s[] = "This is a test";
命令gcc -S t.c
生成文件:
.globl _p
.cstring
LC0:
.ascii "This is a test\0"
.data
.align 2
_p:
.long LC0
.globl _s
_s:
.ascii "This is a test\0"
.subsections_via_symbols
ts.c:
char s[] = "This is a test";
命令gcc -S ts.c
现在生成文件:
.globl _s
.data
_s:
.ascii "This is a test\0"
.subsections_via_symbols
答案 2 :(得分:0)
它们是不同的东西,而不是可互换的。
当你需要指针时使用1);使用2)当你需要一个数组;当你需要一个可调整大小的数组时使用3)
3)
#define LITERAL "..."
char *a = malloc(strlen(LITERAL) + 1);
if (!a) /* no memory; */
strcpy(a, LITERAL);