LINUX.ORG.RU

[C] Нулевые переменные

 


0

0

Глобальные переменные по умолчанию инициализируются нулем, т. е. объявления

int i;
int j = 0;
равносильны. Почему тогда gcc генерирует разный код для них?
    .bss
j:
    .zero 4
.comm i, 4, 4
В описании .comm ничего не сказано об инициализации нулем.

★★★★

Видимо это от того, что в стандарте ничего не сказано об инициализации нулем не статических переменных.

rymis ★★
()

А разве сказано как именно они должны инициализироваться? Сказано только что должны инициализироваться в порядке объявления.

rymis

Видимо это от того, что в стандарте ничего не сказано об инициализации нулем не статических переменных

Чем отличаются статические и глобальные переменные?

Booster ★★
()
Ответ на: комментарий от Booster

По идее, статические должны инициализироваться нулем, в отличие от не статических. На деле:

#1.c
#include <stdio.h>
int i, k=0;
static int j;
main(){
int l;
printf("i=%d, j=%d, k=%d, l=%d\n", i, j ,k, l);
}
Выполняем:
gcc 1.c 
./a.out 
i=0, j=0, k=0, l=134513657
Т.е. получается, что в данном случае gcc все глобальные переменные проинициализировал нулем. Но не факт, что gcc на другой системе (или gcc другой версии) сделает так же.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

По идее, статические должны инициализироваться нулем, в отличие от не статических.

На основание чего была выдвинута такая идея?

bibi
()
Ответ на: комментарий от Eddy_Em

>По идее, статические должны инициализироваться нулем, в отличие от не статических. На деле:
С какой стати?

Booster ★★
()
Ответ на: комментарий от bibi

sorry, тормознул. За исключением области видимости и времени существования между статическими и нестатическими переменными разницы никакой нет. Только что обнаружил, что по умолчанию все глобальные переменные инициируются нулями. Для меня это новость :)

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от rymis

Разве не сказано?

http://c-faq.com/decl/initval.html

Uninitialized variables with static duration (that is, those declared outside of functions, and those declared with the storage class static), are guaranteed to start out as zero, just as if the programmer had typed ``= 0"

Хотя со статическими переменными действительно яснее, они идут в bss:

int i;
static int j;
    .local j
    .comm j, 4, 4
    .comm i, 4, 4
$ nm test.o
00000004 C i
00000000 b j

хотя и объявлены через тот же .comm. Наверно, правильный вопрос - что такое «common symbols» и почему они получаются нулевыми.

unsigned ★★★★
() автор топика
Ответ на: комментарий от unsigned

Дык какая разница-то, статическая или глобальная? Есть память трёх видов: Статическая, динамическая и автоматическая.

Booster ★★
()
Ответ на: комментарий от Eddy_Em

sorry, тормознул. За исключением области видимости и времени существования между статическими и нестатическими переменными разницы никакой нет. Только что обнаружил, что по умолчанию все глобальные переменные инициируются нулями. Для меня это новость :)

Вообще то, стандарт C говорит, что неинициализированные переменные так и остаются неинициализированными т.е. их значение на момент выполнения программы неизвестно. То, что на конкретной системе с конкретным компилятором тот же BSS может заполняться нулями - это все системо-зависимые вещи и на другой системе все может быть совсем по-другому.

bibi
()
Ответ на: комментарий от unsigned

Uninitialized variables with static duration (that is, those declared outside of functions, and those declared with the storage class static), are guaranteed to start out as zero, just as if the programmer had typed ``= 0"

c-faq - это конечно все очень здорово. Но я бы предпочел ссылку на что-то более авторитетное. Например, на соотв. раздел в ISO9899 (стандарт на C99).

bibi
()

Если не изменяет склероз глобальные переменные всегда инициализируются, и если это не сделано явно, то они инициализируются нулевым значением, в C89, в C99 вроде как нет.

Boy_from_Jungle ★★★★
()
Ответ на: комментарий от Boy_from_Jungle

Если не изменяет склероз глобальные переменные всегда инициализируются, и если это не сделано явно, то они инициализируются нулевым значением, в C89, в C99 вроде как нет.

Ну кстати да, в C89:

--- cut ---
If an object that has static storage duration is not initialized explicitly, it is initialized implicitly as if every member that has arithmetic type were assigned 0 and every member that has pointer type were assigned a null pointer constant. If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate./65/
--- cut ---

...а вот в C99 который я смотрел сперва такого нет.

bibi
()
Ответ на: комментарий от bibi

...а вот в C99 который я смотрел сперва такого нет.

Вывод IMHO простой: Если важно, чтобы переменная была проинициализирована, делайте это явным образом. В противном случае, есть шанс в определенной ситуации нарваться на феерические баги.

bibi
()
Ответ на: комментарий от unsigned

Добавь при компиляции -fno-zero-initialized-in-bss и посмотри что получится.

anonymous
()
Ответ на: комментарий от bibi

Добавлю от себя :)
Используйте так называемые «соглашения программистов», т.е. определяйте явно переменные, структуры, указатели, etc, чтобы как писали выше не получать лишней работы.

Boy_from_Jungle ★★★★
()
Ответ на: комментарий от bibi

C99 6.7.8/10

10 If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate. If an object that has static storage duration is not initialized explicitly, then:
— if it has pointer type, it is initialized to a null pointer;
— if it has arithmetic type, it is initialized to (positive or unsigned) zero;
— if it is an aggregate, every member is initialized (recursively) according to these rules;
— if it is a union, the first named member is initialized (recursively) according to these rules.

anonymous
()
Ответ на: комментарий от bibi

3.6.2 Initialization of non-local objects
1
[basic.start.init]
The storage for objects with static storage duration (3.7.1) shall be zero-initialized (8.5) before any other
initialization takes place. Zero-initialization and initialization with a constant expression are collectively
called static initialization; all other initialization is dynamic initialization. Objects of POD types (3.9) with
static storage duration initialized with constant expressions (5.19) shall be initialized before any dynamic
initialization takes place. Objects with static storage duration defined in namespace scope in the same
translation unit and dynamically initialized shall be initialized in the order in which their definition appears
in the translation unit. [Note: 8.5.1 describes the order in which aggregate members are initialized. The
initialization of local static objects is described in 6.7. ]

3.7 Storage duration
1
[basic.stc]
Storage duration is the property of an object that defines the minimum potential lifetime of the storage con-
taining the object. The storage duration is determined by the construct used to create the object and is one
of the following:
— static storage duration
— automatic storage duration
— dynamic storage duration

Booster ★★
()
Ответ на: комментарий от Booster

> Я бы только добавил, что не нулями, а дефолтовыми конструкторами.

Плюсы вынесли мозг?! Какие еще конструкторы в языке С?!

anonymous
()
Ответ на: комментарий от Booster

Ну вот в этом и вопрос, что разницы нет, а код разный.

j ожидаемо попала в bss, который гарантированно заполняется нулями. А i - некий «common symbol», и почему это будет ноль - неясно.

unsigned ★★★★
() автор топика
Ответ на: комментарий от bibi

> Тьфу епрст, на ровном месте пропустил.

Перед сном штудировать стандарт как отче наш! И пока от зубов отскакивать тебе здесь делать нечего!

anonymous
()
Ответ на: комментарий от anonymous

Да на Си почти не пишу, так что почти вынесли.

Booster ★★
()
Ответ на: комментарий от unsigned

Хотя после линковки i тоже попала в bss. Т. е. «common symbols» (как это по-русски?) - это, видимо, нулевые экспортируемые переменные. Странно лишь, что для таких переменных сделали собственный класс.

unsigned ★★★★
() автор топика
Ответ на: комментарий от unsigned

> А i - некий «common symbol», и почему это будет ноль - неясно.

Это не твое дело как там компилятор зануляет глобальные переменные. Сказали зануляет - значит зануляет!

А вообще читай comp.lang.asm.x86 (здесь, например, http://coding.derkeiler.com/Archive/Assembler/comp.lang.asm.x86/2006-05/msg00...)

anonymous
()
Ответ на: комментарий от unsigned

Поправка - common symbols не обязательно нулевые, просто линкер, не найдя другого определения переменной, считает ее нулевой.

А то, что такой код

$ cat main.c
int i;
main() {}
$ cat lib.c
int i = 1;
$ gcc main.c lib.c
вообще работает - это по стандарту или gcc/ld-специфика? Для таких случаев сделан же extern.

unsigned ★★★★
() автор топика
Ответ на: комментарий от anonymous

Да, уже ясно, все свелось к тому же bss. Удивили поначалу промежуточные преобразования.

unsigned ★★★★
() автор топика
Ответ на: комментарий от unsigned

если написать g++ main.c lib.c, то получиться multiple definition of `i'

anonymous
()
Ответ на: комментарий от unsigned

6.9.2 External object definitions Тут всё по стандарту С, но не как в С++.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.