C 程序集中局部和全局作用域中的常量变量

C 程序集中局部和全局作用域中的常量变量,c,assembly,gcc,x86,C,Assembly,Gcc,X86,我在中编译了以下C代码,以了解它如何处理const关键字: int a=1; const b=2; int func () { int c=3; const int d=4; } 据我所知,对于在函数外部定义的变量(文件的全局变量),它会在顶部添加一个标签。但是,如果它是一个const变量,则顶部的变量将放在只读部分中。我的问题是关于以下局部变量: const int d=4; 它的“常量”是如何管理的,因为它只是堆栈上的一个值,堆栈上的任何值都不能自由修改吗?或者,在汇编

我在中编译了以下C代码,以了解它如何处理
const
关键字:

int a=1;
const b=2;
int func () {
    int c=3;
    const int d=4;
}

据我所知,对于在函数外部定义的变量(文件的全局变量),它会在顶部添加一个标签。但是,如果它是一个
const
变量,则顶部的变量将放在只读部分中。我的问题是关于以下局部变量:

const int d=4;

它的“常量”是如何管理的,因为它只是堆栈上的一个值,堆栈上的任何值都不能自由修改吗?或者,在汇编中,是否没有常量局部变量,而这只是编译器强制执行的概念?

如果不使用地址,则不需要在数据内存中的任何位置保留
常量。asm等价物是NASM
d eq 4
或GAS
d=4
,因此您可以在确实需要时将其用作即时消息


与未被修改的非
常量相同:是的,局部变量的constness纯粹是编译器在编译时强制执行的一件事情,以帮助您捕获bug。

如果您不获取地址,则不需要在数据内存中的任何位置保留
常量。asm等价物是NASM
d eq 4
或GAS
d=4
,因此您可以在确实需要时将其用作即时消息

与未被修改的非
常量相同:是的,局部变量的constness纯粹是编译器在编译时强制执行的一件事情,以帮助您捕获bug。

试试看

int fun ( void )
{
    const int d=4;
    return(d);
}

00000000 <fun>:
   0:   e3a00004    mov r0, #4
   4:   e12fff1e    bx  lr



int fun ( void )
{
    const int d=4;
    return(d);
}
int fun1( void )
{
    int d=4;
    d=5;
    return(d);
}
int fun2 ( void )
{
    const int d=4;
    d=5;
    return(d);
}

so.c: In function ‘fun2’:
so.c:16:6: error: assignment of read-only variable ‘d’


int fun ( void )
{
    const int d=4;
    return(d);
}
int fun1( void )
{
    int d=4;
    d=5;
    return(d);
}

00000000 <fun>:
   0:   e3a00004    mov r0, #4
   4:   e12fff1e    bx  lr

00000008 <fun1>:
   8:   e3a00005    mov r0, #5
   c:   e12fff1e    bx  lr
int-fun(无效)
{
常数int d=4;
返回(d);
}
00000000 :
0:e3a00004 mov r0,#4
4:E12FF1E bx lr
int fun(无效)
{
常数int d=4;
返回(d);
}
int fun1(无效)
{
int d=4;
d=5;
返回(d);
}
int fun2(无效)
{
常数int d=4;
d=5;
返回(d);
}
c:在函数“fun2”中:
so.c:16:6:错误:只读变量'd'的赋值
int fun(无效)
{
常数int d=4;
返回(d);
}
int fun1(无效)
{
int d=4;
d=5;
返回(d);
}
00000000 :
0:e3a00004 mov r0,#4
4:E12FF1E bx lr
00000008 :
8:e3a00005 mov r0,#5
c:E12FF1E bx lr
全局变量是全局变量,在某些段中获得内存分配,局部变量是局部变量,除非声明为静态(局部全局变量),否则它们位于堆栈或寄存器中。Const只是向编译器表明,它可以根据变量为只读而不是读/写的假设生成代码。如果试图写入只读声明的变量,更好的编译器会抱怨。所以const int和int之间的区别是read/only和read/write。

试试看

int fun ( void )
{
    const int d=4;
    return(d);
}

00000000 <fun>:
   0:   e3a00004    mov r0, #4
   4:   e12fff1e    bx  lr



int fun ( void )
{
    const int d=4;
    return(d);
}
int fun1( void )
{
    int d=4;
    d=5;
    return(d);
}
int fun2 ( void )
{
    const int d=4;
    d=5;
    return(d);
}

so.c: In function ‘fun2’:
so.c:16:6: error: assignment of read-only variable ‘d’


int fun ( void )
{
    const int d=4;
    return(d);
}
int fun1( void )
{
    int d=4;
    d=5;
    return(d);
}

00000000 <fun>:
   0:   e3a00004    mov r0, #4
   4:   e12fff1e    bx  lr

00000008 <fun1>:
   8:   e3a00005    mov r0, #5
   c:   e12fff1e    bx  lr
int-fun(无效)
{
常数int d=4;
返回(d);
}
00000000 :
0:e3a00004 mov r0,#4
4:E12FF1E bx lr
int fun(无效)
{
常数int d=4;
返回(d);
}
int fun1(无效)
{
int d=4;
d=5;
返回(d);
}
int fun2(无效)
{
常数int d=4;
d=5;
返回(d);
}
c:在函数“fun2”中:
so.c:16:6:错误:只读变量'd'的赋值
int fun(无效)
{
常数int d=4;
返回(d);
}
int fun1(无效)
{
int d=4;
d=5;
返回(d);
}
00000000 :
0:e3a00004 mov r0,#4
4:E12FF1E bx lr
00000008 :
8:e3a00005 mov r0,#5
c:E12FF1E bx lr

全局变量是全局变量,在某些段中获得内存分配,局部变量是局部变量,除非声明为静态(局部全局变量),否则它们位于堆栈或寄存器中。Const只是向编译器表明,它可以根据变量为只读而不是读/写的假设生成代码。如果试图写入只读声明的变量,更好的编译器会抱怨。所以常量int和int之间的区别是只读还是读/写。

我明白了。这样做:
d=5;mov$d,%r9
?是。当然
d=5
实际上更像
static const int d=5在全局范围内(这将类似地优化远离和内联),因为asm实际上没有范围。(除非在函数后手动取消asm符号的设置)我明白了。是否有取消设置符号的说明?或者这仅仅是通过敲击内存位置来完成的?@David542:当然不是指令,这毫无意义。可能存在指令,但结果表明GAS没有
.undef
.unset
,只有
.set
。这是有道理的;asm通常允许引用以后定义的符号,这与C或C宏预处理器不同。感谢您的澄清。关于
静态常量
的一个问题是,变量在哪里初始化(以便gas可以引用它?),它是第一次被引用吗?我问这个问题是因为当我在
gdb
中检查东西时,我没有看到
d=5
指令,所以我猜它是汇编程序内部的,或者什么的(或者我只是缺少了什么)。我明白了。这样做:
d=5;mov$d,%r9
?是。当然
d=5
实际上更像
static const int d=5在全局范围内(这将类似地优化远离和内联),因为asm实际上没有范围。(除非在函数后手动取消asm符号的设置)我明白了。是否有取消设置符号的说明?或者这仅仅是通过敲击内存位置来完成的?@David542:当然不是指令,这毫无意义。可能存在指令,但结果表明GAS没有
.undef
.unset
,只有
.set
。这是有道理的;asm通常允许引用以后定义的符号,这与C或C宏预处理器不同。感谢您的澄清。关于
静态常量
的一个问题是,变量在哪里初始化(以便gas可以引用它?),它是第一次被引用吗?我这样问是因为当我在
gdb
中检查东西时,我没有