Reputation: 2812
Can I set a variable to a certain value at compile time?
If I have a function that changes the value of all struct
s 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
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
Reputation: 146043
Some basic principles of optimization:
But to answer your question...
Always at compile time:
#if
and other preprocessor macro expressionsUsually at compile time:
Upvotes: 3