выделение памяти для объявлений и определений в c - PullRequest
0 голосов
/ 26 сентября 2018

Я попробовал два следующих фрагмента кода:

void swap_woPointer()
{ 
    int a=5;
    static int b=5;
    printf("value of a : %d , value of b: %d \n", a, b);
    printf("address of a: %p , address of b %p \n", &a, &b);

    a++;
    b++;
}



void main(int argc, char *argv[]) 
{
    int ii;
    for (ii=0; ii<10; ii++){
        swap_woPointer();
    }

}

и

void swap_woPointer()
{ 
    int a;
    static int b;
    printf("value of a : %d , value of b: %d \n", a, b);
    printf("address of a: %p , address of b %p \n", &a, &b);

    a++;
    b++;
}



void main(int argc, char *argv[]) 
{
    int ii;
    for (ii=0; ii<10; ii++){
        swap_woPointer();
    }

}

Единственное различие между двумя фрагментами кода состоит в том, что, как только я объявил только переменные a иb

int a;
static int b;

и в другом случае я определил их

int a=5;
static int b=5;

Вывод, который я получаю, отличается для двух случаев.В случае, когда я только объявил переменные, я получаю

value of a : 0 , value of b: 0 
address of a: 0xffffcbbc , address of b 0x100407000 
value of a : 1 , value of b: 1 
address of a: 0xffffcbbc , address of b 0x100407000 
value of a : 2 , value of b: 2 
address of a: 0xffffcbbc , address of b 0x100407000 
value of a : 3 , value of b: 3 
address of a: 0xffffcbbc , address of b 0x100407000 
value of a : 4 , value of b: 4 
address of a: 0xffffcbbc , address of b 0x100407000 
value of a : 5 , value of b: 5 
address of a: 0xffffcbbc , address of b 0x100407000 
value of a : 6 , value of b: 6 
address of a: 0xffffcbbc , address of b 0x100407000 
value of a : 7 , value of b: 7 
address of a: 0xffffcbbc , address of b 0x100407000 
value of a : 8 , value of b: 8 
address of a: 0xffffcbbc , address of b 0x100407000 
value of a : 9 , value of b: 9 
address of a: 0xffffcbbc , address of b 0x100407000

, тогда как если я определяю переменные сразу, я получаю

value of a : 5 , value of b: 5 
address of a: 0xffffcbbc , address of b 0x100402010 
value of a : 5 , value of b: 6 
address of a: 0xffffcbbc , address of b 0x100402010 
value of a : 5 , value of b: 7 
address of a: 0xffffcbbc , address of b 0x100402010 
value of a : 5 , value of b: 8 
address of a: 0xffffcbbc , address of b 0x100402010 
value of a : 5 , value of b: 9 
address of a: 0xffffcbbc , address of b 0x100402010 
value of a : 5 , value of b: 10 
address of a: 0xffffcbbc , address of b 0x100402010 
value of a : 5 , value of b: 11 
address of a: 0xffffcbbc , address of b 0x100402010 
value of a : 5 , value of b: 12 
address of a: 0xffffcbbc , address of b 0x100402010 
value of a : 5 , value of b: 13 
address of a: 0xffffcbbc , address of b 0x100402010 
value of a : 5 , value of b: 14 
address of a: 0xffffcbbc , address of b 0x100402010

Я не понимаю, откуда берется разница,Это как-то связано с распределением памяти.Я подумал, что в обоих случаях я должен получить один и тот же результат, например, переменная a, которая объявлена ​​не статичной, должна размещаться один раз при каждом вызове функции.По-видимому, это только тот случай, когда переменная определена напрямую, а не просто объявлена.

Ответы [ 2 ]

0 голосов
/ 26 сентября 2018

int a; дает вам переменную с неопределенным значением.Что произойдет, если вы напечатаете неопределенное значение, это неопределенное поведение, как объяснено здесь .Значение 0 ни в коем случае не гарантируется.Вы можете получить любое значение, и время от времени оно может отличаться, даже если программа не была перекомпилирована.

Часто некоторые компиляторы, когда они настроены на отладочную сборку, обнуляют всю память, даже если она не инициализирована.Это может объяснить, почему значение кажется детерминированным.Когда вы позже переключитесь на выпуск сборки, вы можете получить мусор.Это явление полезно знать, так как это общее объяснение, почему код ломается в сборке релиза: есть некоторая переменная, которую вы забыли инициализировать, и переключение на сборку релиза выявило ошибку.

В обоих случаях выделяется aв локальном стеке.

Что касается b, существует правило, согласно которому все статические переменные продолжительности хранения, которые не инициализируются программистом, должны быть инициализированы нулем.Следовательно, в случае static int b; вы получите значение 0, которое фактически гарантировано, в отличие от случая int a;.

Кроме того, компиляторы распределяют статические переменные продолжительности хранения в разных сегментах в зависимости от того,инициализируются 0 или другим значением.Те, которые инициализированы в ноль, попадают в сегмент, называемый .bss, а те, которые инициализируются значением, заканчиваются в .data.Вот почему вы получаете разные адреса для b в двух разных случаях: static int b; выделяется в .bss и static int b=5; выделяется в .data.


Примечания к педантичностичитатели:

  • Код фактически не содержит неопределенного поведения, как объяснено в связанном посте.Адрес локальной переменной берется.Предполагается, что основная система без какого-либо представления ловушек двух целых чисел дополнения.

  • Стандарт C не гарантирует, где размещены переменные..stack, .bss и .data являются отраслевыми стандартами де-факто, но не применяются стандартом языка C.

0 голосов
/ 26 сентября 2018

Неинициализированные локальные нестатические переменные (также называемые «автоматическими») действительно неинициализированы.Они будут иметь неопределенное (и, казалось бы, случайное) значение.Не используйте неинициализированные переменные.

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


Чтопроисходит со случаем неинициализированной переменной a, просто это значение того, что находится в памяти, где находится переменная.

Если вы вызываете другие функции, используя локальные (и инициализированные) переменные междутогда вы могли бы получить другие (и непредсказуемые) результаты.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...