Почему gcc дает мне этот результат? - PullRequest
0 голосов
/ 18 февраля 2012

Когда я запускаю этот код, gcc дает мне вывод 10.

Может кто-нибудь объяснить мне, почему он дает мне 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());
}

Ответы [ 6 ]

6 голосов
/ 18 февраля 2012

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

3 голосов
/ 18 февраля 2012

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

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

2 голосов
/ 18 февраля 2012

Здесь:

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

Это означает:

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

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

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

0 голосов
/ 18 февраля 2012

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

0 голосов
/ 18 февраля 2012

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

0 голосов
/ 18 февраля 2012

g возвращает унитализированный varable из стека, в вашем примере это местоположение было в последний раз установлено функцией F, что дает вам ответ x * 2 = 10

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