코딩 - 이 C 함수는 항상 false를 반환해야하지만 그렇지 않습니다.




inline 함수 예제 (3)

Lundin의 훌륭한 답변에서 언급 된 크기 불일치가 실제로 발생하는 곳을 보는 것이 재미 있다고 생각합니다.

--save-temps 컴파일하면 볼 수있는 어셈블리 파일을 얻게됩니다. 다음은 f1()== 0 비교를 수행하고 해당 값을 반환하는 부분입니다.

cmpl    $0, -4(%rbp)
sete    %al

반환 부분은 sete %al 입니다. C의 x86 호출 규칙에서 4 바이트 이하의 반환 값 ( intbool )은 레지스터 %eax 를 통해 반환됩니다. %al%eax 의 가장 낮은 바이트입니다. 따라서 %eax 의 상위 3 바이트는 제어되지 않은 상태로 남아 있습니다.

이제 main() :

call    f1
testl   %eax, %eax
je  .L2

이것은 %eax 전체 가 0인지 검사합니다. int를 테스트한다고 생각하기 때문입니다.

명시 적 함수 선언을 추가하면 main() 이 다음과 같이 변경됩니다.

call    f1
testb   %al, %al
je  .L2

우리가 원하는 것입니다.

나는 오래 전에 포럼에서 흥미로운 질문을 우연히 발견했으며 그 답을 알고 싶습니다.

다음 C 함수를 고려하십시오.

f1.c

#include <stdbool.h>

bool f1()
{
    int var1 = 1000;
    int var2 = 2000;
    int var3 = var1 + var2;
    return (var3 == 0) ? true : false;
}

var3 == 3000 이므로 항상 false 반환해야합니다. main 기능은 다음과 같습니다.

main.c

#include <stdio.h>
#include <stdbool.h>

int main()
{
    printf( f1() == true ? "true\n" : "false\n");
    if( f1() )
    {
        printf("executed\n");
    }
    return 0;
}

f1() 은 항상 false 반환해야하기 때문에 프로그램은 화면에 하나의 false 만 인쇄 할 것으로 예상합니다. 그러나 컴파일하고 실행 한 후에 실행 됨 도 표시됩니다.

$ gcc main.c f1.c -o test
$ ./test
false
executed

왜 그런가요? 이 코드에는 일종의 정의되지 않은 동작이 있습니까?

참고 : gcc (Ubuntu 4.9.2-10ubuntu13) 4.9.2 컴파일했습니다.


main.c에 f1() 에 대해 선언 된 프로토 타입이 없으므로 암시 적으로 int f1() 으로 정의됩니다. 즉, 알 수없는 수의 인수를 사용하고 int 리턴하는 함수입니다.

intbool 의 크기가 다른 경우 동작 정의되지 않습니다 . 예를 들어 내 컴퓨터에서 int 는 4 바이트이고 bool 은 1 바이트입니다. 이 함수는 bool 을 반환하도록 정의 bool 반환 될 때 스택에 1 바이트를 넣습니다. 그러나 main.c에서 int 를 반환하도록 암시 적으로 선언 되었으므로 호출 함수는 스택에서 4 바이트를 읽습니다.

gcc의 기본 컴파일러 옵션은 이것이 수행 중임을 알려주지 않습니다. 그러나 -Wall -Wextra 컴파일하면 다음을 얻을 수 있습니다.

main.c: In function ‘main’:
main.c:6: warning: implicit declaration of function ‘f1’

이 문제를 해결하려면 main 앞에 main.c에 f1 에 대한 선언을 추가하십시오.

bool f1(void);

인수 목록은 명시 적으로 void 설정되어 있으며, 알 수없는 수의 인수를 의미하는 빈 매개 변수 목록과 달리 함수가 인수를 사용하지 않도록 컴파일러에 지시합니다. f1.c의 f1 정의도이를 반영하여 변경해야합니다.


다음과 같은 명령으로 컴파일하십시오 :

gcc -Wall -Wextra -Werror -std=gnu99 -o main.exe main.c

산출:

main.c: In function 'main':
main.c:14:5: error: implicit declaration of function 'f1' [-Werror=impl
icit-function-declaration]
     printf( f1() == true ? "true\n" : "false\n");
     ^
cc1.exe: all warnings being treated as errors

이러한 메시지가 있으면이를 해결하기 위해 수행 할 작업을 알아야합니다.

편집 : (현재 삭제 된) 주석을 읽은 후 플래그없이 코드를 컴파일하려고했습니다. 글쎄, 이로 인해 컴파일러 오류 대신 컴파일러 경고가없는 링커 오류가 발생했습니다. 그리고 이러한 링커 오류를 이해하기가 더 어려우므로 -std-gnu99 가 필요하지 않더라도 적어도 -Wall -Werror 사용하여 엉덩이에 많은 고통을 덜어줍니다.





gcc