Что происходит, когда мы не используем оператор return в вызывающей функции в C? - PullRequest
1 голос
/ 24 апреля 2019

Хотелось бы узнать вывод приведенной ниже программы. Главное, что происходит, когда мы не используем оператор return в вызывающей функции?

int sum(int x, int y)
{
    //return x+y; 
}

int main()
{
    int res=0;
    res=sum(1,2);
    printf("res = %d\n",res);
}

в вышеуказанной функции sum(), если я использую return x+y; он будет печатать 3 как вывод?

Что произойдет, если я не буду использовать оператор return?

Ответы [ 2 ]

5 голосов
/ 24 апреля 2019

См. 6.9.1 (определения функций) / 12 в черновом стандарте C11 (тот же язык появляется в C99):

  1. Если достигнут }, который завершает функцию, и вызывающая сторона использует значение вызова функции, поведение не определено.

(В C90 был в основном эквивалентный язык в 6.6.6.4 (оператор return):

Если выполняется оператор return без выражения и значение вызова функции используется вызывающей стороной, поведение не определено. Достижение }, которое завершает функцию, эквивалентно выполнению оператора return без выражения.

Разница в том, что (начиная с C99) наличие return; без выражения в не пустой функции является ошибкой.)

В вашем случае достигается } из sum (оператор return не выполнялся) и используется возвращаемое значение:

res=sum(1,2);

Поэтому ваш код имеет неопределенное поведение: может произойти все что угодно, от значения мусора в res до бесконечного цикла или сбоя.

0 голосов
/ 24 апреля 2019

ответ melpomene является 100% правильным с точки зрения чистого языка: возврат из не пустой функции без возвращаемого значения неизменно приводит к неопределенному поведению.После этого все ставки выключены.

Я собираюсь добавить к этому, что произойдет вероятно :

Когда вы вызываете функцию, компиляторимеет набор правил, которым следует, как параметры и возвращаемое значение передаются вызываемому объекту.Эти правила в духе «Если первый аргумент является целочисленным типом, поместите его в регистр eax перед вызовом вызываемого».Итак, если вы скажете foo(42), компилятор выдаст код для загрузки 42 в регистр eax, а затем для вызова foo, который затем просто проверяет значение, найденное в регистре eax, чтобы узнать, что былопередано.

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

Итак, когда вызабудьте назвать возвращаемое значение, возвращаемое значение просто не будет установлено.Что бы ни находилось в соответствующем регистре / ячейке памяти, будет интерпретироваться как возвращаемое значение вызывающим абонентом. То, что именно "передается" обратно вызывающему, зависит на 100% от того, как происходит вызываемый объект.быть скомпилированным, и это может быть детерминированным.Рассмотрим этот фрагмент кода:

int getSecret() {
    return 42;
}

int checkSecret(int guess) {
    int secret = getSecret();
    //return secret == guess;
}

int main() {
    printf("The secret is %d.\n", checkSecret(0));
}

Если вы скомпилируете и запустите этот код, вы можете обнаружить, что он правильно печатает секретное значение 42.Зачем?Просто: когда getSecret() возвращает секретное значение, оно помещает его туда, где checkSecret() ожидает найти возвращаемое значение.И это может быть тот же регистр, в котором main() ожидает найти возвращаемое значение checkSecret().

С точки зрения языка это нормально: когда checkSecret() возвращается без установки возвращаемого значения, язык позволяет всему происходить, включая утечку секрета. Вот почему забывание возвращаемого значения может стать дырой в безопасности .Это может позволить злоумышленнику либо извлечь информацию, которую он не должен знать, либо инициировать пути выполнения кода, которые невозможны при правильном поведении, потому что функция «возвращает» значение, которое не находится в ожидаемом диапазоне возвращаемых значений.

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