假设我有一个以这种方式返回C字符串的简单函数:
const char * getString()
{
const char * ptr = "blah blah";
return ptr;
}
Run Code Online (Sandbox Code Playgroud)
我以这种方式从main()调用getString():
Run Code Online (Sandbox Code Playgroud)const char * s = getString();
1)根据gdb,变量ptr存储在堆栈中,但ptr指向的字符串不是:
(gdb) p &ptr
$1 = (const char **) 0x7fffffffe688
(gdb) p ptr
$2 = 0x4009fc "blah blah"
Run Code Online (Sandbox Code Playgroud)
这是否意味着"blah blah"不是getString()中的局部变量?
我想如果它是一个局部变量,我将无法将它传递给我的main()函数......但如果它不存在,它存储在哪里?在堆上?这是OS每次点击字符串时实现的"一种"动态内存分配,还是什么?
2)如果我使用数组而不是指针,这样:
const char *getString2()
{
const char a[] = "blah blah blah";
return a;
}
Run Code Online (Sandbox Code Playgroud)
编译器警告我:
warning: address of local variable ‘a’ returned
(当然程序编译,但它不起作用).
实际上,如果我问gdb,我会的
(gdb) p &a
$2 = (const char (*)[15]) 0x7fffffffe690
Run Code Online (Sandbox Code Playgroud)
但我认为const char*ptr和const char a []基本上是一回事.看起来他们不是.
我错了吗?什么是两个版本之间的差异?
谢谢!
小智 7
当你写作
const char *ptr = "blah blah";
Run Code Online (Sandbox Code Playgroud)
然后发生以下情况:编译器生成带有内容的常量字符串(类型char [])并将其"blah blah"存储在可执行文件的数据段中的某处(它基本上具有与使用static关键字声明的变量类似的存储持续时间).
然后,该字符串的地址(在程序的整个生命周期内有效)存储在ptr指针中,然后返回该指针.一切都很好.
这是否意味着它
"blah blah"不是getString()中的局部变量?
让我用一句破碎的英语句子回答:是的,事实并非如此.
但是,当您声明一个数组时,如
const char a[] = "blah blah";
Run Code Online (Sandbox Code Playgroud)
那么编译器不会生成静态字符串.(实际上,这在初始化字符串时有点特殊.)然后生成代码,为a 数组分配足够大的堆栈内存(它不是指针!),并用字符串的字节填充它.这a 实际上是一个局部变量,并返回其地址导致未定义的行为.
所以...
但我认为,
const char *ptr和const char a[]基本上是同样的事情.
不,完全没有,因为数组不是指针.
我想如果它是一个局部变量,我将无法将它传递给我的 main() 函数......但如果它不是,它存储在哪里?
字符串文字通常存储在只读数据段 ( .rodata) 中。C 标准只是说它们有静态存储持续时间。因此,您可以返回指向此类文字的指针,但数组则不然。
在下面的示例中, 指向的对象p1具有静态存储持续时间,而数组p2具有自动存储持续时间。
char *f(void)
{
const char *p1 = "hello, world";
char p2[] = "hello, world";
return p1; /* allowed */
return p2, /* forbidden */
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
802 次 |
| 最近记录: |