История изменений
Исправление firkax, (текущая версия) :
у него просто один неверный возврат (без результата) сразу следует за верным возвратом с результатом в регистре. но если между этими возвратами будет еще какой-то его код, использующий этот регистр - то результат будет испорчен.
Эм, разумеется. Только это не «код удачный», а все мои рассуждения касались именно случая «вызов в конце с забытым return». Если ты забудешь return в середине то там гарантированно будет не то что нужно - ведь код дальше вообще не должен был выполняться, и ассемблерные фокусы тут будут уже ни при чём.
опять же результат можно возвращать и через стек например(теоретически)
Я почти уверен что платформ (не самодельных одного анонимуса), где int возвращается через стек, не существует.
----------- Кстати, пример можно расширить и передавать вовращаемое значение через протекающую абстракцию void-функции:
#include <stdio.h>
int f1(void) {
return 42;
}
void f2(void) {
f1();
}
int f3(void) {
if(0) return 123;
f2();
}
int main(void) {
printf("f3 = %d\n", f3());
return 1;
}
Правда если включить хотя бы -O1 то компилятор начинает тут всё инлайнить и портит фокус (причём с int f2() тоже портит). Но это из-за того что функции слишком простые.
Вот такое работает даже с -O2
#include <stdio.h>
void a_wrapper(void) { a_counter(); }
int a_counter(void)
{
char c;
if ((c = getchar()) == '.') {
return 0;
} else if (c == 'a') {
return a_counter() + 1;
} else {
a_wrapper();
}
}
int main(void) {
printf("%d\n", a_counter());
return 0;
}
Исправление firkax, :
у него просто один неверный возврат (без результата) сразу следует за верным возвратом с результатом в регистре. но если между этими возвратами будет еще какой-то его код, использующий этот регистр - то результат будет испорчен.
Эм, разумеется. Только это не «код удачный», а все мои рассуждения касались именно случая «вызов в конце с забытым return». Если ты забудешь return в середине то там гарантированно будет не то что нужно - ведь код дальше вообще не должен был выполняться, и ассемблерные фокусы тут будут уже ни при чём.
опять же результат можно возвращать и через стек например(теоретически)
Я почти уверен что платформ (не самодельных одного анонимуса), где int возвращается через стек, не существует.
----------- Кстати, пример можно расширить и передавать вовращаемое значение через протекающую абстракцию void-функции:
#include <stdio.h>
int f1(void) {
return 42;
}
void f2(void) {
f1();
}
int f3(void) {
if(0) return 123;
f2();
}
int main(void) {
printf("f3 = %d\n", f3());
return 1;
}
Правда если включить хотя бы -O1 то компилятор начинает тут всё инлайнить и портит фокус (причём с int f2() тоже портит). Но это из-за того что функции слишком простые.
Исправление firkax, :
у него просто один неверный возврат (без результата) сразу следует за верным возвратом с результатом в регистре. но если между этими возвратами будет еще какой-то его код, использующий этот регистр - то результат будет испорчен.
Эм, разумеется. Только это не «код удачный», а все мои рассуждения касались именно случая «вызов в конце с забытым return». Если ты забудешь return в середине то там гарантированно будет не то что нужно - ведь код дальше вообще не должен был выполняться, и ассемблерные фокусы тут будут уже ни при чём.
опять же результат можно возвращать и через стек например(теоретически)
Я почти уверен что платформ (не самодельных одного анонимуса), где int возвращается через стек, не существует.
----------- Кстати, пример можно расширить и передавать вовращаемое значение через протекающую абстракцию void-функции:
#include <stdio.h>
int f1(void) {
return 42;
}
void f2(void) {
f1();
}
int f3(void) {
if(0) return 123;
f2();
}
int main(void) {
printf("f3 = %d\n", f3());
return 1;
}
Правда если включить хотя бы -O1 то компилятор начинает тут всё инлайнить и портит фокус. Но это из-за того что функции слишком простые.
Исходная версия firkax, :
у него просто один неверный возврат (без результата) сразу следует за верным возвратом с результатом в регистре. но если между этими возвратами будет еще какой-то его код, использующий этот регистр - то результат будет испорчен.
Эм, разумеется. Только это не «код удачный», а все мои рассуждения касались именно случая «вызов в конце с забытым return». Если ты забудешь return в середине то там гарантированно будет не то что нужно - ведь код дальше вообще не должен был выполняться, и ассемблерные фокусы тут будут уже ни при чём.
опять же результат можно возвращать и через стек например(теоретически)
Я почти уверен что платформ (не самодельных одного анонимуса), где int возвращается через стек, не существует.