문제

테스트는 다음과 같은 코드:

#include <stdio.h>
#include <stdlib.h>
main()
{
    const char *yytext="0";
    const float f=(float)atof(yytext);
    size_t t = *((size_t*)&f);
    printf("t should be 0 but is %d\n", t);
}

컴파일:

gcc -O3 test.c

좋은 출력해야한다:

"t should be 0 but is 0"

하지만 gcc4.1.3,가:

"t should be 0 but is -1209357172"
도움이 되었습니까?

해결책

를 사용하여 컴파일러 플래그-fno-는 엄격한이 들어있습니다.

와 함께 엄격한싱 활성화,그것은 기본적으로 적어도-O3,라인:

size_t t = *((size_t*)&f);

컴파일러에서는 size_t*하지 않는 지점으로 동일한 메모리 영역으로 떠*.내가 알기로는,이것은 표준을 준수하는 행위(준수를 엄격한싱 규칙에서 ANSI 표준에 시작 주위에 gcc-4,스 Kammeyer 지적했).

면 내가 기억이 올바르게 사용할 수 있습니다 중간 캐스팅을 char*하여 이를 떠올릴 수 있을 것입니다.(컴파일러에서 char*할 수 있는 별칭이 아무것도)

다시 말해서,이 시도(을 테스트 할 수 없습니다 그것을 자신이 지금 그러나 내가 생각하는 작동합니다):

size_t t = *((size_t*)(char*)&f);

다른 팁

에 C99 표준이며,이에 의해 덮여 다음과 같은 규칙에 6.5-7:

체하여 저장된 값만 액세스 lvalue 식 있는 중 다음과 같은 유형:73)

  • 유형과 호환되는 효과적인 유형의 객체

  • 된 버전의 유형과 호환되는 효과적인 유형의 객체

  • 는 형식의 서명된 또는 부호 없는 형식에 해당하는 효과적인 유형의 체

  • 는 형식의 서명된 또는 부호 없는 형식에 해당하는 자격을 갖춘전 효과적인 유형의 객체

  • 집계 또는 조합형을 포함하는 하나의 상기 유형 중 원(를 포함하여,재귀적으로,구성원의 subaggregate 거나 포함되는 연합)또는

  • 는 캐릭터는 유형입니다.

마지막 항목은 왜 주 먼저(char*)작동합니다.

이것은 더 이상 허용에 따라 C99 규칙에서 포인터이 들어있습니다.포인터가 두 개의 서로 다른 종류 수 없는 지점과 동일한 위치 메모리에 있습니다.이 규칙의 예외는 무효과 char 포인터입니다.

그래서 당신의 코드가 포인터의 size_t,컴파일러를 무시하도록 선택할 수 있습니다이다.을 얻고 싶은 경우 플로트 값으로 size_t,다만 할당 및 플로트 캐스팅 될 것입니다(잘 반올림하지는 않습)이와 같:

size_t 크기=(size_t)(f);//이 작동

이것은 일반적으로 보고되는 버그가 있지만,사실은 정말 수 있는 기능을 최적화하는 작업을 더 효율적으로 합니다.

에서 gcc 해제할 수 있습니다 이 컴파일러로 전환합니다.내가 믿-fno_strict_aliasing.

그것은 나쁜 C 코드:-)

문제가 되는 부분입니다 액세스하는 한 개체를 float 형식으로 캐스팅 정수 포인터와 참조습니다.

이를 나누기싱 규칙이 있습니다.컴파일러는 가정하는 무료는 포인터를 다른 유형과 같은 떠나 int 겹치지 않도록 메모리에 있습니다.을 했을 정확히입니다.

무엇을 컴파일러가 보고는 당신이 뭔가를 계산,스토어에서 그것을 떠 f 에 접근하지 않습니다.대부분 컴파일러가 제거된 부분의 코드고정 적이 일어났습니다.

은 참조를 통해 귀하의 size_t 포인터는 것입니다 이 경우에는 일부가 초기화되지 않은 가비지에서 스택입니다.

당신이 할 수 있는 두 가지 작동하는-이:

  1. 사용 조합으로 부유물 및 size_t 멤버고 캐스팅을 통해 유형 말장난.하지만 작동합니다.

  2. 사용 memcopy 의 내용을 복사하 f 로 size_t.컴파일러는 스마트 충분히 검출하고 최적화합니다.

왜 당신이 생각하는 것 t 해야 0?

또,더 accuractely 표현한,"왜 당신이 생각하는 바이너리의 표현을 공중에 떠있는 영 것과 같은 이진 표현의 정수 영?"

이것은 나쁜 C 코드입니다.당신의 캐스팅을 끊 C 싱 규칙,그리고 최적화는 무료 할 것 이 코드입니다.당신은 아마는 GCC 는 cheduled 의 size_t 읽기 전에는 부동 소수점 쓰(기 숨기기 fp 파이프라인 지연).

당신은 설정할 수 있습니다-fno-엄격한싱 스위치를 사용,또는 연합 또는 reinterpret_cast 으로 재해석해 보는 가치에 표준을 준수하는 방법입니다.

따로 포인터 선형,당신이 기대하는 sizeof(size_t)==sizeof(float).나는 생각하지 않는(에서 64 비트 size_t 해야 64 비트이지만 떠 32 비트),를 의미하는 코드를 읽을 것이다가 초기화되지 않았습니다.

-O3 지 않은 것으로 간주"sane",-O2 은 일반적으로 위 임계값을 제외하고 어쩌면 일부는 멀티미디어 앱입니다.

일부 애플 리케이션을 수 없어도 그렇게 멀리 가고,죽는 경우에 당신은 넘어 갈-O1.

이 있는 경우 새로운 충분한 GCC(나 4.3 여기),그것은 수도에서 이러한 명령을 지원

  gcc -c -Q -O3 --help=optimizers > /tmp/O3-opts

면 조심해야합니다,당신은 아마도를 통해 갈 수 있는 목록을 찾을 준수 최적화를 가능하는 원인이 버그가 있습니다.

man gcc :

  The output is sensitive to the effects of previous command line options, so for example it is possible to find out which
       optimizations are enabled at -O2 by using:

               -O2 --help=optimizers

       Alternatively you can discover which binary optimizations are enabled by -O3 by using:

               gcc -c -Q -O3 --help=optimizers > /tmp/O3-opts
               gcc -c -Q -O2 --help=optimizers > /tmp/O2-opts
               diff /tmp/O2-opts /tmp/O3-opts | grep enabled

테스트 코드:"i686-사과-darwin9-gcc-4.0.1(GCC)4.0.1(Apple Inc.를 구축 5465)"

고 있었다 문제 없습니다.출력:

t should be 0 but is 0

그래서 거기에서 버그 당신은 코드입니다.는 것을 의미하지는 않는 것이 좋 코드입니다.그러나 나는 추가 returntype 의 주요 기능 그리고"return0;"의 끝에서 기능이다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top