2012-02-18 4 views
0

Когда я запускаю этот код, gcc дает мне результат 10.Почему gcc дает мне этот результат?

Может кто-нибудь объяснить мне, почему он дает мне 10? :)

#include <stdio.h> 

int f(int x) { 
    int y; 
    y = 2*x; 
} 

int g() { 
    int z; 
    return z; 
} 

int main() { 
    int x=5; 
    f(x); 
    printf("%d\n",g()); 
} 
+1

Вы не должны компилировать свои C-программы без -Wall, IMO. –

ответ

2

Здесь:

int g() { 
    int z; 
    return z; 
} 

Это читает:

int g(): 
    reserve memory for an integer, call it z. 
    return whatever is in that reserved memory. 

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

Вы делаете то же самое в своей другой функции. То, что вы делаете, это чтение неинициализированной памяти. Вы можете получить эту информацию за дополнительной информацией. См. Также «стек» и «куча», динамическая память и другие связанные темы.

+0

Это прояснилось для меня. Благодарю. :) – Gaui

6

это неопределенное поведение - вы ссылаетесь на переменную, которая не имеет значения, установленного для нее. Вероятно, он дает 10, потому что компилятор использовал ту же ячейку памяти для переменной в f(), но нет никакой гарантии, что она не должна зависеть от нее и является не чем иным, как любопытством.

0

г возвращает инициализированы varable из стека, в вашем примере, что местоположение последнего набора с помощью функции F дает вам ответ на х * 2 = 10

3

Там нет ничего объяснять. Ваш код демонстрирует неопределенное поведение в двух отдельных, не связанных случаях: первый f ничего не возвращает, несмотря на то, что он объявлен как возвращаемый int, а второй потому, что g возвращает неинициализированное значение.

Практически, как функции будут помещены в стек вызовов будет вызван местный y (который в конечном счете имеет значение 10), чтобы быть в том же месте, что и возвращаемого значения g() в printf вызова, так что вы чтобы увидеть значение 10. Но это более или менее везение.

+0

Строго говоря, 'f()' не имеет неопределенного поведения, так как значение функции не используется. Однако, очевидно, это проблемная область. –

+0

@MichaelBurr: У меня была эта неопределенная идея, что «не возвращать значение из не-void-функции» уже UB, а не просто использовать возвращаемое значение этой функции позже. Я должен был бы проверить. И C может отличаться от C++ в этом отношении. –

0

Поскольку вы не инициализируете z, и он использует то же местоположение в стеке, что и y. Поскольку вы не инициализируете его, старое значение все еще существует.

0

Это прекрасный пример того, почему люди боятся оптимизаций и когда они хвастаются поисками ошибок компилятора для своих боссов. Этот код, как указывали другие, будет вызывать предупреждения об использовании неинициализированных переменных в g(). С настройками вашего компилятора он использует старое значение в стеке от вызова до f(5). С различными настройками оптимизации компилятора, скорее всего, это повлияет на то, как переменные оказываются в стеке, и в результате вы получите разные результаты, когда вы вносите изменения, которые не связаны друг с другом. Это неопределенное поведение, и нет никаких гарантий того, какое значение будет иметь значение, однако его обычно легко объяснить, понимая порядок вызова и то, как компилятор устанавливает стек. Если есть предупреждения, когда вы устраняете это странное поведение, сначала исправьте предупреждения, а затем задайте вопросы о том, почему.

Смежные вопросы