среда, 9 мая 2012 г.

Tentative definition


Заметил одну интересную вещь. Если написать программу

int x = 0;

то внешняя переменная x, как ей и полагается, находится в .bss секции, где инициализируется нулём. Тоже самое должно происходить и с программой

int x;

ведь внешние переменные без явной инициализации должны обнуляться. Но если собирать такую программу командой
gcc -c test.c

т.е. как объектный файл, то переменной x в секции .bss не будет. Но при этом в таблице символов она присутствует и более того, если программу слинковать, то она в той секции окажется. Возникает вопрос: "Почему?".

На самом деле во втором случае имеет место не совсем определение переменной 'x'. В стандарте такая штука зовётся "tentative definition" (предварительное определение). Поведение такой штуки задаётся следующим образом: если не было внешних определений для данного идентификатора, то его поведение полностью идентично тому, как если бы он инициализировлся нулём.

При наличии же внешних объявлений, конструкция int x; просто считается объявлением идентификатора, определённого в другой единице трансляции. После линковки x примет то значение, которым его определили. Например:

// file.c #include <stdio.h>

int x;
int main() { printf("%d\n", x); }

$ gcc file.c && ./a.out
0


Т.е. поведение полностью идентично int x = 0; но если сделать следующим образом:

// add.c

int x = 1;

// file.c

#include <stdio.h>

int x;
int main() { printf("%d\n", x); }

$ gcc file.c add.c && ./a.out
1


то поведение изменится. Т.к. определяется такое поведение во время связывания, то запихнуть 'x' в секцию .bss без онного просто нельзя. Этим и объясняется отсутствие 'x' в .bss, но присутствие в таблице символов.

Комментариев нет:

Отправить комментарий