Linux 용 i386 또는 x86-64 용으로 표준 ABI를 사용할 때 경고 메시지가 표시되지 않습니다. 왜 그런지 설명해 드리겠습니다.
첫째, gcc's documentation에 대한 -Wcast-align
말을 무슨 보자 : 포인터가 대상의 요구 정렬이 증가되도록 주조 할 때마다
이 경고. 예를 들어 정수가 2 바이트 또는 4 바이트 경계에서만 액세스 할 수있는 컴퓨터에서
char *
이
int *
으로 캐스팅되면 경고합니다.
인텔 아키텍처에서는 범용 명령어를 사용할 때 정수 정렬이 필요하지 않습니다. 더블 워드,
단어 및 quadwords 자연 경계의 메모리 으로 정렬 할 필요가 없습니다 : 장 단어의 4.1.1 정렬, 더블 워드, Quadwords, 더블 Quadwords, Intel's Basic Architecture manual에서 인용. 단어, 더블 워드, 및 쿼드 워드에 대한 자연 경계는 짝수 번호의 주소이며, 균등하게 나눌 수있는 주소는 이며, 주소는 각각 8로 나눌 수 있습니다. 그러나 프로그램의 성능을 향상 시키려면 이 가능할 때마다 (특히 스택) 데이터 구조가 자연 경계에 정렬되어야합니다.
따라서 정렬을 반드시 권장하지는 않지만 적극 권장합니다. 그러나이 규칙에는 한 가지 예외가 있습니다. EFLAGS
레지스터의 비트 18을 "정렬 검사"비트라고하며 CR0
레지스터의 비트 18을 "정렬 마스크"플래그라고합니다. 둘 다 1로 설정되면 "자연 경계"에 정렬되지 않은 데이터에 대한 모든 메모리 액세스 (단어의 경우 2 바이트, 더블 워드의 경우 4 바이트 등)는 #AC
, 정렬 검사 예외 . 이에 대해 자세히 알아 보려면 Intel System Programming Guide을 확인하십시오.
그러나 System V ABI for i386 및 System V ABI for x86-64은 EFLAGS의 정렬 플래그가 설정되어 있지 않습니다. 사실, I386 ABI는 29 페이지, 장 3-3 기계 인터페이스에 다음과 같은주의 사항 :
Intel386 아키텍처는 모든 데이터가 가 제대로 정렬로 액세스 할 필요가 없습니다. (...) 결과적으로 포인터가 참조 해제 또는 참조 인수와 같은 임의의 데이터 액세스는 이 올바르게 정렬되었거나되지 않을 수 있습니다. 잘못 정렬 된 데이터에 액세스하는 것은 올바르게 정렬 된 데이터에 액세스하는 것보다 느리며 그렇지 않으면 차이가 없습니다.
또한 권장되지만 :
컴파일러 적절한 배향과 독립적 인 데이터 객체를 할당한다.
GCC는 코드를 컴파일하는 플랫폼의 ABI를 항상 알고 있으며 - x86/64의 경우 - 정렬되지 않은 데이터 액세스가 허용된다는 사실을 알고 있습니다. 당신은 ARM의 GCC 툴체인이 코드를 컴파일하려고하면
int main(void)
{
char foo[] = "foobar";
int bar = *(int*)(foo + 1);
return 0;
}
, 당신은 얻을 것이다 :이 같은 코드 정렬에 대한 경고없이 컴파일 이유 (의는 다음 예에 엄격한 앨리어싱 규칙에 대해 잊지하자)입니다 경고 :
[email protected]:/tmp$ arm-linux-gnueabi-gcc -Wcast-align align.c
align.c: In function 'main':
align.c:4:13: warning: cast increases required alignment of target type [-Wcast-align]
int bar = *(int*)(foo + 1);
이것은 일반적으로 정렬되지 않은 액세스가 ARM에서는 가장 많이 피하기 때문입니다. 저는 ARM 전문가가 아니므로 그 이상의 것을 말할 수는 없습니다.
또한 대부분의 내용은 SSE/AVX에 적용되지 않습니다.
컴파일러는 아마 배열을 정렬하고 감지합니다. 포인터 매개 변수 대신'data + 1 '을 사용해보십시오. – Medinoc
배열 포인터를 캐스팅하기 때문에 그것이라고 생각합니다. 데이터를 변수로 사용하여 코드를 실행 한 결과, 경고가 완벽하게 전달되었습니다. – Haris
char * data = "aaaaa"; int ptr = * ((int *) data); 경고 메시지가 표시되지 않습니다. 내가 무엇이 누락 되었습니까? – linuxfreak