C变量的范围[重复]
Posted
技术标签:
【中文标题】C变量的范围[重复]【英文标题】:Scope of C variables [duplicate] 【发布时间】:2012-08-21 18:21:58 【问题描述】:可能重复:Is returning a string literal address from a function safe and portable?“life-time” of string literal in C
你好,我有点困惑
char *func()
return "Hello";
这里的“Hello”是字符序列/数组。它是一个局部变量,一旦函数返回,它就必须消失。那我们怎么能得到正确的值呢?
【问题讨论】:
那不是UB吗?你有没有收到编译器的警告? 不,在这种情况下不是,因为字符串存储在一个常量内存地址中。 但是他返回的是char*
而不是const char*
不是UB吗?
@NeelBasu 是否没有在堆栈上分配字符串文字?
@Constantinius 是否没有在堆栈上分配字符串文字?
【参考方案1】:
"Hello"
是一个字符串文字,将在程序的生命周期内存在。引用 C99 标准的相关部分:
6.2.4 对象的存储时长...然后使用多字节字符序列来初始化一个静态存储持续时间数组,长度刚好足以包含该序列...
一个对象,其标识符是用外部或内部链接声明的,或者用 存储类说明符 static 具有静态存储持续时间。它的生命周期是整个 程序的执行及其存储的值仅在程序之前初始化一次 启动。
函数的返回值应为const char*
,因为尝试修改字符串文字是未定义的行为。
【讨论】:
Strin 字面量是否没有存储在堆栈中?它们是从堆中分配的吗? @GreatCoder 它们被分配在只读内存中,可能称为.rodata
或类似的链接器乱码。
@GreatCoder,它们不存储在堆栈或堆中。它们将直接在生成的二进制文件中编译。我认为将字符串文字编译到的二进制区域称为数据区。
@hmjd 通常,链接器将有一个段 .data
和一个段 .rodata
,前者用于所有静态存储持续时间变量(未初始化为零,位于 .bss 中)后者用于只读变量,即常量和字符串字面量。
@Lundin,谢谢。我知道这两个部分(已初始化和未初始化),但不知道名称。【参考方案2】:
看看这个:Is returning a string literal address from a function safe and portable?
即使字符串被删除(局部变量或使用 malloc() 和 free() 进行动态分配),当您返回指针时,该值也可能是正确的。但是,这是一种未定义的行为。
【讨论】:
【参考方案3】:该函数仅在返回控件后才销毁值。因此,在遇到 return 语句时,将“Hello”放置为返回值,然后该函数销毁范围;
【讨论】:
那么它应该在运行时崩溃。问题提到“那我们怎么能得到正确的值” 你错了,因为字符串文字不是本地(自动)变量,也不是在堆栈上分配,而是作为常量、静态只读内存。【参考方案4】:它是常量并且在内存中有固定的地址。
【讨论】:
怎么样?他从未指定const
@NeelBasu 好的,更准确地说是字符串字面量。
字符串文字总是如此。以上是关于C变量的范围[重复]的主要内容,如果未能解决你的问题,请参考以下文章