C 为什么局部常量变量不转到.rodata部分? #包括 void公司(int*p){ *p=*p+1; } int main(){ 常数INTA=10; 公司(a),; printf(“%d\n”,a); }

C 为什么局部常量变量不转到.rodata部分? #包括 void公司(int*p){ *p=*p+1; } int main(){ 常数INTA=10; 公司(a),; printf(“%d\n”,a); },c,compiler-construction,constants,elf,C,Compiler Construction,Constants,Elf,上面的程序编译时没有任何错误,输出为11,因为局部变量“a”进入堆栈 所以我的问题是: 为什么“a”进入堆栈。我希望它能进入。罗达区。但为什么没有呢 而如果我将“a”声明为全局常量变量,它将进入.rodata部分 这让我很开心 编译器可以做任何它想做的事情。如果您将其声明为static,则可能会得到您要查找的行为 在这种特定情况下,您试图修改常量值,导致了未定义的行为,因此实际上所有下注都是无效的 例如,我刚刚用构建了您的精确程序,得到了10的输出。它确实发出了关于丢弃const限定符的警告:

上面的程序编译时没有任何错误,输出为11,因为局部变量“a”进入堆栈

所以我的问题是:

  • 为什么“a”进入堆栈。我希望它能进入。罗达区。但为什么没有呢
  • 而如果我将“a”声明为全局常量变量,它将进入.rodata部分
    这让我很开心

    编译器可以做任何它想做的事情。如果您将其声明为
    static
    ,则可能会得到您要查找的行为

    在这种特定情况下,您试图修改
    常量
    值,导致了未定义的行为,因此实际上所有下注都是无效的

    例如,我刚刚用构建了您的精确程序,得到了
    10
    的输出。它确实发出了关于丢弃
    const
    限定符的警告:

    #include <stdio.h>
    
    void inc(int* p) {
            *p = *p + 1;
    }
    
    int main() {
            const int a = 10;
            inc(&a);
            printf("%d\n",a);
    }
    

    编译器可以做任何它想做的事情。如果您将其声明为
    static
    ,则可能会得到您要查找的行为

    在这种特定情况下,您试图修改
    常量
    值,导致了未定义的行为,因此实际上所有下注都是无效的

    例如,我刚刚用构建了您的精确程序,得到了
    10
    的输出。它确实发出了关于丢弃
    const
    限定符的警告:

    #include <stdio.h>
    
    void inc(int* p) {
            *p = *p + 1;
    }
    
    int main() {
            const int a = 10;
            inc(&a);
            printf("%d\n",a);
    }
    

    除了名称之外,const不在C中声明常量,而是不可修改的变量。它必须在“堆栈”上实现,因为函数的递归调用必须导致该变量的不同实例化。(可以通过它们的地址来区分。)在您的例子中,您的函数不会递归导致可能的优化,但不必采用这种优化路径


    至于违反
    const
    属性,每个编译器都必须给您一个“诊断”,说明这是您自己的风险。

    除了名称之外,表明
    const
    不在C中声明常量,而是声明不可修改的变量。它必须在“堆栈”上实现,因为函数的递归调用必须导致该变量的不同实例化。(可以通过它们的地址来区分。)在您的例子中,您的函数不会递归导致可能的优化,但不必采用这种优化路径

    至于违反
    const
    属性,每个编译器都必须给您一个“诊断”,这是您自己的风险。

    在C中,“常量变量”实际上是您承诺不更改的变量,仅此而已。如果它是函数的局部变量,则会像任何其他变量一样创建、初始化和随后销毁它。唯一的区别是,如果你(公然)试图改变它,你会被尖叫。即:

    example.c:9:13: warning: passing 'const int *' to parameter of type 'int *' discards qualifiers [-Wincompatible-pointer-types]
            inc(&a);
                ^~
    example.c:3:15: note: passing argument to parameter 'p' here
    void inc(int* p) {
                  ^
    1 warning generated.
    
    在C语言中,“常量变量”实际上是承诺不改变的变量,仅此而已。如果它是函数的局部变量,则会像任何其他变量一样创建、初始化和随后销毁它。唯一的区别是,如果你(公然)试图改变它,你会被尖叫。即:

    example.c:9:13: warning: passing 'const int *' to parameter of type 'int *' discards qualifiers [-Wincompatible-pointer-types]
            inc(&a);
                ^~
    example.c:3:15: note: passing argument to parameter 'p' here
    void inc(int* p) {
                  ^
    1 warning generated.
    

    是的,我看到它是一个未定义的行为,静态将解决这个问题。但我只是想知道为什么gcc会这样做,以及背后是否有任何原因?!?当涉及到未定义的行为时,您可以依赖的唯一原因是编译器工程师最容易实现的。即使这样也很难保证。好吧,我看到由于糟糕的程序员,编译器编写者的工作变得很困难。我无法投票,但谢谢你的回答!!:)是的,我看到它是一个未定义的行为,静态将解决这个问题。但我只是想知道为什么gcc会这样做,以及背后是否有任何原因?!?当涉及到未定义的行为时,您可以依赖的唯一原因是编译器工程师最容易实现的。即使这样也很难保证。好吧,我看到由于糟糕的程序员,编译器编写者的工作变得很困难。我无法投票,但谢谢你的回答!!:)C标准允许常量变量变异。用C++编译器,你会得到编译器错误。它是允许一个const变量被变异的C标准。使用C++编译器将获得编译器错误。