我可以在编译时将变量设置为某个值吗?
如果我在程序初始化时有一个更改所有struct
s值的函数,如果我在编译时这样做,我会节省大量时间并使用处理器,是吗?
我了解到静态和全局变量将其值初始化为0
。如果我声明static int a = 3;
,则编号或运行时将分配号码3
?如果是的话,对于文字也是如此吗?我怎么知道它是否属实? (我不知道如何使用调试。)
我也学习了常量C表达式,但我无法理解它是什么。它会对我有用吗?它是什么?
更新:我只会问如果我可以在编制时更改变量的值! (还有一些东西......)
答案 0 :(得分:3)
优化的一些基本原则:
但要回答你的问题......
始终在编译时:
#if
和其他预处理器宏表达式通常在编译时:
答案 1 :(得分:1)
如果我理解你的问题,你很好奇哪种变量放在哪种data segments中。
未初始化的全局变量和函数级static
变量进入bss
部分,它实际上只是对象文件中的一个数字,告诉链接器/加载器为该部分留出多少空间加载程序或库时:
$ readelf --sections /bin/sh
There are 28 section headers, starting at offset 0x195e8:
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
...
[26] .bss NOBITS 0000000000619500 00019500
0000000000002bd0 0000000000000000 WA 0 0 32
这是在运行时为未初始化的变量留出的0x2bd0 == 11216字节。
初始化的全局变量存储在data
或rodata
部分中:
$ readelf --sections /bin/sh
There are 28 section headers, starting at offset 0x195e8:
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
...
[16] .rodata PROGBITS 0000000000412de0 00012de0
0000000000003482 0000000000000000 A 0 0 32
...
[25] .data PROGBITS 0000000000619300 00019300
0000000000000200 0000000000000000 WA 0 0 32
抱歉,我忘记了编译器/链接器用来决定哪些变量进入只读部分以及哪些变量进入读/写部分的确切规则。但足以说链接器会将页面保护设置为{em>只读 rodata
部分,并且尝试写入此部分将生成页面错误并可能终止该程序。 / p>
char *string = "hello world"; /* "hello world\0" goes into rodata
char *string goes into data */
我希望在编译时计算任何基于文字整数,浮点和sizeof()
运算的计算。
一个很小的例子:
$ cat test.c
int i;
int main(int argc, char *argv[]) {
return 0;
}
$ gcc -o test test.c
$ size test
text data bss dec hex filename
1044 496 24 1564 61c test
C库带来了很多的额外行李。但请注意当我们初始化i
时会发生什么,bss
尺寸下降,data
尺寸上升:
$ cat test.c
int i=1+2;
int main(int argc, char *argv[]) {
return 0;
}
$ gcc -o test test.c
$ size test
text data bss dec hex filename
1044 500 16 1560 618 test
$
我认为bss
在我的系统上被限制为8
的倍数,因为它是符合AMD64标准的CPU。其他系统可能需要4
的倍数。
$ cat test.c
int i=sizeof(int);
int main(int argc, char *argv[]) {
return 0;
}
$ gcc -o test test.c
$ size test
text data bss dec hex filename
1044 500 16 1560 618 test
$
请注意,切换到sizeof(int)
不会增加text
(可执行代码)大小,也不会更改data
大小。