#c #compiler-construction #stack #stack-trace
#c #компилятор-конструкция #стек #трассировка стека
Вопрос:
int fun()
{
printf("ncrap");
}
void main()
{
printf("n return value of fun %d", fun());
}
и, пожалуйста, не могли бы вы объяснить, как стек выделяет память для возвращаемых значений и как здесь работает стек.
Комментарии:
1. Я знаю, что это зависит от архитектуры, но я прошу об общем.
Ответ №1:
fun
вызывает неопределенное поведение.
Пожалуйста, всегда компилируйте со всеми включенными предупреждениями компилятора. Это должно выдать вам предупреждение о том, что вы совершаете ту самую ошибку.
Ваше main
также вызывает неопределенное поведение, потому что стандарт C требует, чтобы вызывалась только одна функция, main
и она возвращала int
. Однако вам разрешено, в качестве особого случая, опустить return
оператор в вашей (исправленной) main
функции.
«Стек», как вы предполагаете, не является частью языка C . Но это не имеет значения; стандарт гласит, что возвращаемый объект создается в области вызывающего, и это все, что вам нужно знать.
(Практически, невозвращенная int
, вероятно, закончится как неинициализированная переменная типа int
, но стандарт гласит, что вызов функции уже запускает неопределенное поведение, а не просто доступ для чтения позже.)
Комментарии:
1. Нет, всегда компилируйте с включенными некоторыми предупреждениями компилятора. Включая это 😉 (хотя 1)
2. Итак, вы имеете в виду, что все может быть напечатано ??… С помощью -Wall он выдает предупреждение… Но мне любопытно узнать о стеке… Я имею в виду, что хранится в стеке??
3. @Invictus: Ну, поскольку
%d
означает «типint
«, я полагаю, да, может быть напечатано любое целое значение . «Неопределенное поведение» фактически означает, что программа может вести себя любым образом (сбой, форматирование вашего жесткого диска, заказ пиццы). Практически, хотя я полагаю, вы всегда доберетесь доprintf
строки. Майкл: Я имел в виду что-то вроде-Wall
; не обязательно «все неясные и сомнительные предупреждения». Краткость — душа nit, не так ли?
Ответ №2:
Это неопределенное поведение. Может произойти все, что угодно.
Ответ №3:
Поскольку это зависит от архитектуры, общего понятия не существует.
Однако можно допустить, что значение, которое вычисляется последним, или возвращаемое значение из последней вызванной функции, может быть возвращено. Но в итоге это неопределенное поведение. Если вы хотите на это положиться…
Обратите также внимание, что для int main()
существует особый случай. (Кстати: void main()
не является стандартным.) Если оператор return не присутствует, он возвращает 0
.