【问题标题】:static const char* VS const char* in CC 中的静态 const char* VS const char*
【发布时间】:2020-08-01 23:20:54
【问题描述】:

C语言中const char*static const char*有什么区别?

我认为Difference between static const char* and const char*的答案是错误的。

确实,const char* 元素放在程序的.rodata 部分,否则会导致段错误:

const char* f() {
    const char* hello = "hello";
    return hello;
}

int main() {
    const char* hello_after = f();
    printf("%s\n", hello_after);
}

确实,由于该代码有效,f 返回的指针仍然指向活动数据,这表明该数据不是在堆栈上分配,而是存储在.rodata 中。

但是,在我看来,就 GCC 而言,const char*static const char* 是相同的东西。

但是,为什么 const int*static const int* 的行为不一样?这是一个例外,在 GCC 中硬编码,仅适用于 char 类型,然后 conststatic const 应该相同?

非常感谢您的帮助!

【问题讨论】:

  • 这与const char* 的关系较小,而与字符串文字(在这种情况下为"hello")的关系更大
  • 我认为您误解了链接的答案。他们讨论了指针的存储位置——而不是字符串文字。根据static的使用,指针的存储方式会有所不同@
  • 如果你用-fsanitize=address编译你会得到一个运行时错误(godbolt.org/z/37rH-L
  • 引用:“确实,const char* 元素被放在程序的 .rodata 部分......” 错误 - 字符串文字是但不是指针。

标签: c memory static string-literals


【解决方案1】:

在这个函数声明中

const char* f() {
    const char* hello = "hello";
    return hello;
}

指针 hello 指向具有静态存储持续时间的字符串文字“hello”。也就是说,具有静态存储持续时间的不是指针,而是具有静态存储持续时间的指向文字。在函数的每次调用中,指针都会重新初始化。

如果你会像这样声明函数

const char* f( ) {
    static const char* hello = "hello";
    return hello;
}

那么在这种情况下,指针本身具有静态存储持续时间。它在程序获得控件之前被初始化一次,并且它的值在函数调用之间保持。

例如考虑这个演示程序。

#include <stdio.h>

const char* f( int i ) 
{
    static const char* hello = "hello";

    if ( i == 1 ) hello = "bye";
    else if ( i == -1 ) hello = "hello";

    return hello;
}

int main(void) 
{
    puts( f( 0 ) );
    puts( f( 1 ) );
    puts( f( 0 ) );

    return 0;
}

它的输出是

hello
bye
bye

那最初是指针 hello 由字符串文字“hello”初始化的。

然后由于这个电话

    puts( f( 1 ) );

其值已更改。现在它指向字符串字面量“bye”。

第三次通话

    puts( f( 0 ) );

指针保留上次调用函数时分配给它的值。

这是由于指针具有静态存储持续时间。

【讨论】:

  • 谢谢你,我明白你的回答了!所以我想这里的独特之处在于我们正在处理字符串文字?相反,如果我们有 const int hello[5] = {1,2,3,4,5}; ,则“数组文字” {1,2,3,4,5} 不会被 GCC 存储在 .rodata 中?
  • @CosmoSterin 在该示例中,您有一个数组对象,而不是指针对象,这会改变一些事情。实现可以在幕后做任何事情,给出正确的结果,但请注意,如果函数是递归输入的,则必须有两个具有不同地址的 hello 数组。
  • 好的!我现在不知道 C 对数组的处理方式与对指针的处理方式不同。
  • @CosmoSterin 这个 {1,2,3,4,5} 不是“数组文字”。这是用于初始化数组元素的初始化程序。它与您将在块作用域中编写的相同 char s[] = "hello";用于初始化数组的字符串文字的字符。但是如果声明数组本身没有存储说明符static,则该数组本身没有静态存储时长。
猜你喜欢
  • 2011-02-25
  • 2012-07-21
  • 1970-01-01
  • 2013-01-26
  • 1970-01-01
  • 1970-01-01
  • 2013-11-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多