문제

다음 전환이 안전합니까?

int b[10][10];
char *x;
int a[]={0,1,2,3,4,5,6,7,8,9};

for(int i=0;i<10;i++)
  for(int j=0;j<10;j++)
    b[i][j]=a[i];

for(x=(char *)&b[0];x<=(char *)&b[9][9];x+=sizeof(a+1)) // Problem lies here!
    printf("%d\n",*x);

나는 위의 전환을 생각하지 않습니다 for 루프는 안전합니다 (플랫폼 의존적이라고 생각합니다). 내가 틀렸다면 저를 바로 잡으십시오. 코드가 컴파일 된 경우에도 경고없이 컴파일하기 때문에 놀랐습니다 -Wall -pedantic GCC의 옵션.

도움이 되었습니까?

해결책

이 모든 것은 하나의 이유에 대해 합법적 일 가능성이 있습니다. int 배열 객체는 배열로 재 해석됩니다 char 사물. 일반적으로 메모리 재 해석은 정의되지 않은 동작으로 이어지지 만 언어 사양은 명시 적으로 [서명/부호없는] char"배열 모든 유형의 객체에 대한 재 해석을 허용합니다.

그러나 한 가지 공식적인 안전 문제가 여전히 있습니다. 언어는 비트 패턴이 유효한 값이라고 보장하지 않습니다. char 유형. 재 해석 된 메모리를 읽으려는 시도 char 유형은 이론적으로 함정 표현을 만나면 정의되지 않은 행동을 유발할 수 있습니다. char. 여기에서 안전하려면 unsigned char 트랩 표현이없는 유일한 유형입니다. 물론, 트래핑이있는 플랫폼 char "이국어"라고 안전하게 호출 할 수 있습니다.

한편, 당신의 sizeof(a + 1) 말이되지 않는 것 같습니다. a + 1 표현입니다 int * 유형. 포인터 크기를 사용하여 증가하는 이유 x 이 경우 가치는 나에게 명확하지 않습니다. 무엇을 성취하려고 했습니까?

경고가 없다는 점에 관해서는 ... 컴파일러가 여기서 경고를 발행 할 것으로 기대하지 않을 것입니다. GCC는 종종 유형 기획 (일명 메모리 재 해석)에 대해 경고하지만 char 재 해석은 명시 적으로 허용되며 (위에서 언급했듯이) 여기에는 경고가 없습니다. 더욱이, 명백한 캐스트는 일반적으로 경고를 억제하는 경향이 있습니다. 왜냐하면 컴파일러에게 얼마나 잘못되었는지에 관계없이 무언가를하고 싶어한다고 컴파일러에게 알리는 방법이기 때문입니다.

다른 팁

char*에 대한 모든 포인터 유형의 캐스트는 C 언어에 의해 명시 적으로 허용됩니다. 그래서 이것의 대부분은 괜찮습니다.

for(x=(char *)&b[0]; x <= (char *)&b[9][9]; x += sizeof(a+1))  

첫 번째 부분은 괜찮습니다 x = (char*)&b[0]; 배열의 시작에 대한 숯 포인터를 설정합니다. 테스트도 괜찮습니다 x <= (char *)&b[9][9] X가 배열 내부에 가리키는 한 사실입니다.

x += sizeof(a+1) iffy 부분입니다. 대부분의 32 비트 CPU 아키텍처 크기 (int*) 발생합니다 Sizeof (int)와 동일 하므로이 코드는 아마도 일하다, 그러나 우연히만.

의도 된 것이 무엇인지 확신합니다 x += sizeof(a[0]) 또는 x += sizeof(b[0]), 그러나 코드가 실제로 의도 된 것을 수행 한 이후 아무도 버그를 눈치 채지 못했습니다.

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