在C中,在编译时评估什么?

时间:2011-05-23 22:11:16

标签: c

我可以在编译时将变量设置为某个值吗?

如果我在程序初始化时有一个更改所有struct s值的函数,如果我在编译时这样做,我会节省大量时间并使用处理器,是吗?

我了解到静态和全局变量将其值初始化为0。如果我声明static int a = 3;,则编号或运行时将分配号码3?如果是的话,对于文字也是如此吗?我怎么知道它是否属实? (我不知道如何使用调试。)

我也学习了常量C表达式,但我无法理解它是什么。它会对我有用吗?它是什么?

更新:我只会问如果我可以在编制时更改变量的值! (还有一些东西......)

2 个答案:

答案 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字节。

初始化的全局变量存储在datarodata部分中:

$ 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大小。