LINUX.ORG.RU

История изменений

Исправление 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 возвращается через стек, не существует.