定义指向静态字符串的指针

时间:2009-11-20 12:05:51

标签: c

here中,对于全局变量,可以使用以下形式:

(1) const char *a = "...";

不如:

(2) const char a[] = "..."

为什么呢?我一直认为(1)更好,因为(2)实际上复制了我们分配它的字符串,而(1)只指向它。

3 个答案:

答案 0 :(得分:3)

livejournal链接的参数是(1)通过创建单独的指针变量和安全漏洞引入了不必要的间接级别,因为指针变量可能被覆盖。假设以下两个声明:

char  *p = "This is a test";
char s[] = "This is a test";

假设这些声明属于文件范围,因此ps都具有静态范围。

这是一个假设的记忆图,显示了所有内容的布局:

 
                    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    ...

链接中显示的参数如下:

  1. 附加变量 - p是与其引用的字符串不同的对象;它本身不包含字符串值,而s则包含;
  2. 更多攻击点,变量可写 - 可以重新分配p指向其他地方(可能是包含恶意代码的段),而您无法重新分配{{1 }}。
  3. 额外的重新安置 - 不确定这是指什么(对于我做的工作,我从来没有真正担心机器级别的性能,所以我不是熟悉所有术语);
  4. 获取字符串地址需要内存加载并且访问字符串本身需要两次内存加载 - 如果您通过s读取字符串,首先必须加载内容0x00010000获取字符串地址(0x00008000),然后您必须加载0x00008000的内容以获取字符串值本身。如果您正在执行 lot ,那么使用char数组并删除一个间接级别可能会导致显着的性能提升。
  5. 总之,您需要交换一点内存以提高速度和安全性。当然,这假设一个特定的操作环境,并且可能不适用于普遍的。

答案 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);