2016-12-11 6 views
1

У меня есть вопрос о неопределенной переменной и демонстрируемой отрезала кода внизу:Неопределенная переменная и оптимизация компилятора

func_1() После --- он будет толкать A в стек и установить значение этой памяти в 40 а затем вытащите A из стека.

После func_2() --- он будет толкать A в стек снова и наследуют его значение до и распечатывают значение будет 40.

void func_1() 
{ int A = 40;} 

void func_2() 
{ int A; printf("%d/n",A);} 

void main (void) 
{ 
    func_1(); 
    func_2(); 
} 

Если изменить имя A в func_2() в B к проверить использование стека и поместить дополнительный код в нем, чтобы проверить использование пула названных переменных:

int A; printf("%d\n", A); 

на моем компьютере, он говорит B 40, A is 0.

Что мне было интересно, если у компилятора есть пул с именованными переменными, которые он повторно использует, чтобы помочь ему оптимизировать скомпилированный код (?), То почему я получил 0 на A? Когда компилятор использует пул?

Мой вопрос основан на слайде: http://www.slideshare.net/olvemaudal/deep-c/131-I_am_now_going_to

+0

Звучит так, как будто он сильно зависит от компилятора.Но если я правильно понимаю, в 'func_2' вы печатаете' B', а затем 'A', что означает, что, поскольку вы сначала выделяете' B', это займет значение последней вещи, которая была в стеке ('A 'from' func_1'), а следующее распределение (' A' из 'func_2') будет следующим байтом после этого. – Iluvatar

+2

Изменение имени от A до B не сопровождает ничего, не говоря уже о «проверке использования стека». Нет такой вещи, как «пул именованных переменных». Неясно, что вы спрашиваете. – EJP

+1

Без конкретной архитектуры недопустимо считать стек или любую другую конкретную модель памяти для автоматических переменных. И что вы подразумеваете под «пулом»? Это не имеет смысла в этом контексте. Имена (соответственно идентификаторы) находятся в таблице символов вместе с другими свойствами объектов, которые они идентифицируют. – Olaf

ответ

3

Скорее всего в функции func_2(); переменная A выделяется в ту же позицию стеки, что значение 40 было сохранено (в func_1()). Поскольку вы не инициализировали переменную в func_2(), она напечатает переменную со случайным значением, которое оно находится в памяти в этом случае 40 (потому что оно никогда не переписывалось). Это похоже на сценарий, когда пользователь освобождает указатель, а также утверждает, что он тоже может видеть его утверждение после, хотя они могут или не видят это неопределенное поведение. Излишне говорить, что вы не должны полагаться на такое поведение!

Я сделал простой тест, чтобы доказать, что он не имеет ничего общего с именами:

void func_1() 
{ 
    int A = 40; 
    int B = 10; 
    printf("Memory A = %p Memory B = %p\n",&A, &B); 
} 

void func_2() 
{ int B; printf("B = %d Memory B = %p\n",B, &B);} 

void main (void) 
{ 
    func_1(); 

    func_2(); 
    printf("\n"); 
} 

выход:

Memory A = 0x7fff58f86b5c Memory B = 0x7fff58f86b58 
B = 40 Memory B = 0x7fff58f86b5c 

Как вы можете видеть, хотя B = 10 в func_1() в func_2() Значение печати было 40, почему? если вы проверяете адрес памяти переменной A в func_1(), это 0x7fff58f86b5c - тот же адрес памяти, занимаемый переменной B в func_2().

+0

Вы имели в виду * should not *? – GurV

+0

LOL, да;) спасибо за указание на то, что – dreamcrash

3

Персонаж на слайде играет роль идиота, изобретающего идею, которая, кажется, объясняет поведение, которое он не понимает. Нет пула именованных переменных.

Поведение этого кода не определено и на него нельзя положиться. Если это происходит во время выполнения, чтобы распечатать значение 40, это просто случайность реализации.