drigoSkalWalker
drigoSkalWalker

Reputation: 2812

In C, what is evaluated in compile time?

Can I set a variable to a certain value at compile time?

If I have a function that changes the value of all structs at the program initialization, if I do it in compile time I save a lot of time and use of the processor, can I?

I learned that static and global variables initialize their values as 0. If I declare like static int a = 3;, the number 3 will be assigned in compile or run time? If yes, it's true to compond literals too? How can I know if it is true? (I don't know how to use a debug for that.)

I learned about constant C expressions too, but I can't understand what this is. Will it be of any use to me? What is it?

UPDATE: I ONLY ASKING IF I CAN CHANGE A VALUE OF A VARIABLE IN COMPILE TIME!!! (and another some things...)

Upvotes: 2

Views: 300

Answers (2)

sarnold
sarnold

Reputation: 104050

If I understand your question, you're curious about which kinds of variables get placed into which kinds of data segments.

Uninitialized global variables and function-level static variables go into the bss section, which is really just a number in the object file telling the linker/loader how much space to set aside for the section when loading the program or library:

$ 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

That's 0x2bd0 == 11216 bytes to be set aside at runtime for uninitialized variables.

Global variables that are initialized are stored into the data or rodata section:

$ 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

Sorry, I've forgotten the exact rules the compiler / linker use to decide which variables go into the read only section and which variables go into the read / write section. But suffice to say that the linker will set the page protections to read only for the rodata section, and attempts to write to this section will generate a page fault and probably terminate the program.

char *string = "hello world"; /* "hello world\0" goes into rodata
                                 char *string goes into data */

I would expect any computation based solely on literal integers, floating point, and sizeof() operations to be computed at compile-time.

A very small example:

$ 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

The C library brings along a lot of extra baggage. But notice what happens when we initialize i, the bss size goes down, the data size goes up:

$ 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
$ 

I assume the bss is constrained to a multiple of 8 on my system, because it is an AMD64-compliant CPU. Other systems might require a multiple of 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
$ 

Note that switching to sizeof(int) didn't increase the text (executable code) size, and didn't change the data size either.

Upvotes: 1

DigitalRoss
DigitalRoss

Reputation: 146043

Some basic principles of optimization:

  • only optimize measured (profiled) bottlenecks, don't waste time optimizing imaginary or hypothetical issues, unless you are a subject-matter expert who is reimplementing a known compute-time issue
  • don't optimize anything unless it's in a loop

But to answer your question...

Always at compile time:

  • static initialization
  • #if and other preprocessor macro expressions

Usually at compile time:

  • Any expression involving only constants

Upvotes: 3

Related Questions