Функция возвращает значение без оператора возврата - PullRequest
18 голосов
/ 10 января 2011

Почему следующий код имеет правильный вывод?int GGT не имеет оператора return, но код все равно работает?Не заданы глобальные переменные.

#include <stdio.h>
#include <stdlib.h>

int GGT(int, int);

void main() {
    int x1, x2;
    printf("Bitte geben Sie zwei Zahlen ein: \n");
    scanf("%d", &x1);
    scanf("%d", &x2);
    printf("GGT ist: %d\n", GGT(x1, x2));
    system("Pause");
}

int GGT(int x1, int x2) {
    while(x1 != x2) {
        if(x1 > x2) {
            /*return*/ x1 = x1 - x2;
        }
        else {
            /*return*/ x2 = x2 - x1;
        }
    }
}

Ответы [ 5 ]

31 голосов
/ 10 января 2011

Как минимум для x86, возвращаемое значение этой функции должно быть в регистре eax. Все, что было там, будет считаться возвращаемым значением вызывающей стороной.

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

15 голосов
/ 10 января 2011

Он не должен работать и, конечно, не работать на всех компиляторах и целевых ОС, даже если он работает на вашей.

Вероятное объяснение состоит в том, что функция, возвращающая int, всегда что-то возвращает, и обычно это содержимое регистра. Вероятно, случается, что регистр, используемый для возвращаемого значения, в вашем случае аналогичен используемому для вычисления последнего выражения перед возвратом из функции (для целей x86, конечно, eax).

При этом оптимизирующий компилятор, обнаруживающий отсутствие возврата, может полностью удалить код этой функции. Отныне эффект, который вы видите (может), исчезает при активации более высоких уровней оптимизации.

Я проверил это с помощью gcc:

GCC без оптимизации: входы 10, 20 -> результат 10

gcc -O1 входы 10, 20 -> результат 1

gcc -O2 входы 10, 20 -> результат 0

3 голосов
/ 10 января 2011

На x86 возвращаемое значение сохраняется в регистре EAX, который "случайно" также используется этим компилятором для хранения результата арифметических операций (или, по крайней мере, вычитания).Вы можете проверить это, посмотрев сборку, сгенерированную вашим компилятором.Я согласен с Криссом - вы не можете предполагать, что так будет всегда, поэтому лучше явно указать возвращаемое значение.

0 голосов
/ 08 февраля 2013

GCC вставляет команду "ret" в этом случае, в то время как clang вставляет "ud2" и приложение вылетает во время выполнения.

0 голосов
/ 10 января 2011

Вам не нужно возвращать оператор, если вы используете указатели. Как правило, вы можете вернуть только одно значение с помощью оператора Return, но если вы используете указатели, вы можете вернуть сколько хотите.

scanf ("% d", & x1); там вы даете функции адрес X1, а не значение X1. указатели работает ширина адреса. Вы можете читать книги, узнавать, как работают указатели.

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