回答
在LiveJournal的链路的参数是:(1)通过创建一个单独的指针变量,并在安全孔引入了一个间接的unneccesary水平指针变量可能被覆盖。假定以下两个声明:
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
到别处点(也许包含恶意代码段),而你不能重新分配s
。 - 额外的搬迁 - 不知道这是指什么(对于我所做的工作,我从来没有真正担心机器级别的性能,所以我不熟悉所有的术语);
- 获取字符串地址需要内存加载并访问字符串本身需要两次内存加载 - 如果您通过
p
读取字符串,首先必须加载0x00010000的内容以获取字符串地址(0x00008000 ),那么你必须加载0x00008000的内容来获取字符串值本身。如果你正在做一个很多,然后用字符数组和切割出一层间接可能导致noticable的性能提升。
总之,你交易,以提高速度和安全性一点记忆。当然,这是假定一个特定的操作环境,并不一定适用。
我必须坚持,因为我对PMG的评论的回复一样,那是你只定义了's',那么就不必包含目标文件中的文本字符串,所以你*不*买卖内存速度更快(和更安全的访问),你正在节省内存*和*更快,更安全的访问。实际上,OP提供的链接提倡使用较低内存使用的''样式定义。我会用证明更新我的答案。 – 2009-11-20 15:22:14
这是一个很好的解释,除了这个结论“权衡”的评论。 – 2009-11-20 15:23:01
在编写动态库的上下文中的“附加重定位” - 加载库时,必须根据库的加载地址更新对静态对象的所有引用。第一种情况有两个静态对象('a'和未命名的字符数组),而第二种情况只有一个。 – caf 2009-11-21 02:54:17
在(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
不。在1)'a'是一个指针,它的内容是一个指向字符串文字的指针; 2)'了'是一个数组,其内容是构成字符串文字字符** **复制为阵列创建 – pmg 2009-11-20 12:12:49
@pgm然而,在2内存),并因为它是一个全球性的,我们正在谈论在这里,复制是在编译时进行的。在“副本”之后,可以从二进制文件中省略现在没用的字符串文字。你可能想到'char a [] =“...”;'作为提供全局char数组的初始化的一个方便的语法。 – 2009-11-20 14:11:30
严格地说,不是“因为它是全球性的”,而是“因为它具有静态存储时间”。 – caf 2009-11-21 02:47:46
他们是不同的东西,而不是可更换间。
使用1)当你需要一个指针;使用2)当你需要一个数组时;使用3)当你需要一个可调整大小的阵列
3)
#define LITERAL "..."
char *a = malloc(strlen(LITERAL) + 1);
if (!a) /* no memory; */
strcpy(a, LITERAL);
- 1. 静态指针
- 2. C++的typedef静态函数指针:未定义的符号
- 3. 指定一个字符串值指针
- 4. 分配静态内存的结构中定义的字符指针在C
- 5. 指定字符串指向字符指针
- 6. 复制字符串指针,指针
- 7. 如何定义指向sqlite3结构的静态指针? C++
- 8. Android非静态字符串静态字符串错误
- 9. c字符串指针
- 10. c字符串指针
- 11. 字符串指针和strcpy
- 12. 指针和字符串
- 13. 字符串指针功能
- 14. C字符串和指针
- 15. 字符串指针修改
- 16. C,指针,字符串
- 17. C字符串和指针
- 18. Java - 静态定义的字符列表
- 19. 将const指针定义为const字符串
- 20. 动态字符指针数组为字符串
- 21. 字符指针和字符串
- 22. Bada,静态指针崩溃
- 23. 静态变量指针?
- 24. C#指针 - 静态调用
- 25. 如何定义静态提升共享指针?
- 26. 停留在定义静态指针,并用它
- 27. C#静态类与预定义字符串的struct
- 28. Wrtiting字符串内存流 - 指向字符串的指针
- 29. 使用指向字符串的指针初始化指向字符串中的字符的指针
- 30. 指针指向字符串和STRCMP
另见我的回答对您的[前一个问题] [^ 1]为什么最好使用数组与指针。 [^ 1]:http://stackoverflow.com/questions/1769089/defining-const-pointer-to-a-const-string/1769163#1769163 – LnxPrgr3 2009-11-20 17:30:10