2012-08-06 3 views
8

this question에서 노동 조합의 정렬은 개인 구성원 중 가장 큰 정렬보다 적지 않다고 생각하기 시작할 수 있습니다. 하지만 gcc/g ++의 long long 유형에 문제가 있습니다. 전체 예제는 here를 찾았지만, 여기에 관련된 내 질문에 대한 부분입니다 수 있습니다왜 긴 long 유니온 멤버의 정렬이 포함 된 유니온/struct보다 큰가? 이 올바른지?

sizeof(long long): 8 
__alignof__(long long): 8 
sizeof(ull): 8 
__alignof__(ull): 4 
sizeof(sll): 8 
__alignof__(sll): 4 

왜보다 더 큰 조합원의 정렬입니다 : 이것은 다음과 같은 출력 결과

union ull { 
    long long m; 
}; 

struct sll { 
    long long m; 
}; 


int main() { 
#define pr(v) cout << #v ": " << (v) << endl 
    pr(sizeof(long long)); 
    pr(__alignof__(long long)); 
    pr(sizeof(ull)); 
    pr(__alignof__(ull)); 
    pr(sizeof(sll)); 
    pr(__alignof__(sll)); 
}; 

포함 노조의 alignof 키스의 대답 에 따르면

[업데이트]

여기에 잘못된 것입니다. 그러나 나는 다음을 시험해 본다. alignof는 우리에게 사실을 말해 준다. 참조 :

union ull { 
    long long m; 
}; 
long long a; 
char b; 
long long c; 
char d; 
ull e; 
int main() { 
#define pr(v) cout << #v ": " << (v) << endl 
    pr(size_t((void*)&b)); 
    pr(size_t((void*)&c)); 
    pr(size_t((void*)&d)); 
    pr(size_t((void*)&e)); 
    pr(size_t((void*)&c) - size_t((void*)&b)); 
    pr(size_t((void*)&e) - size_t((void*)&d)); 
}; 

출력은 :

size_t((void*)&b): 134523840 
size_t((void*)&c): 134523848 
size_t((void*)&d): 134523856 
size_t((void*)&e): 134523860 
size_t((void*)&c) - size_t((void*)&b): 8 
size_t((void*)&e) - size_t((void*)&d): 4 

그래서, long long의 정렬은 8과 long long을 포함하는 노동 조합의 정렬은 글로벌 데이터에서 4입니다. 로컬 범위의 경우 컴파일러가 로컬 데이터를 다시 정렬 할 수 있으므로이 테스트를 수행 할 수 없습니다. 따라서이 트릭이 작동하지 않습니다. 이것에 대해 논평 해 주시겠습니까?

[/ UPDATE]

+1

Red Hat에서는 gcc 4.7.0과 함께 '-m32'와 동일한 것을 보지만'-m64'(모두'8's)와는 같지 않습니다. – BoBTFish

+1

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52023 _Alignof (C11)에 해당하는 gcc 버그 링크. –

답변

7

__alignof__ (a GCC 확장되는) 반드시 유형의 필요한 얼라인먼트를보고하지 않는다.

x86 프로세서는 모든 유형에 실제로 1 바이트 이상의 정렬이 필요하지 않습니다. 4 바이트 또는 8 바이트 객체에 대한 액세스는 객체가 워드로 정렬되지만 바이트 정렬이면 충분할 수 있습니다.

일부 기계가 실제로 정렬을 필요로하지 않는다;

(가) gcc documentation 인용 홀수 번지의 데이터 형식에 대해서도 참조 번호 을 허용합니다. 이러한 시스템의 경우 __alignof__은 GCC가 데이터 유형을 지정하는 최소 정렬을보고합니다. 대개 대상 ABI가 지정합니다.

하지만 여전히 실제로는 대답하지 않습니다. 그 느슨한 정의에도 불구하고 에 대한 long long에 대한 더 엄격한 정렬을 나타내는 좋은 이유는 long long을 포함하는 구조체 또는 공용체에 대한 것보다 생각할 수 없습니다.

타입의 배향을 결정하는 이식성 방법이있다 :

#define ALIGNOF(type) ((int)(offsetof(struct {char c; type t;}, t))) 

이것은 chart 이루어진 구조체의 유형 t의 멤버의 오프셋을 산출한다.이 매크로를 사용하여,이 프로그램 : long long이 있습니다

sizeof(long long): 8 
__alignof__(long long): 8 
ALIGNOF(long long): 4 
sizeof(ull): 8 
__alignof__(ull): 4 
ALIGNOF(ull): 4 
sizeof(sll): 8 
__alignof__(sll): 4 
ALIGNOF(sll): 4 

결과는 ALIGNOF() 매크로 일치 제에 의해 표시 :

#include <iostream> 
#include <cstddef> 

union ull { 
    long long m; 
}; 

struct sll { 
    long long m; 
}; 

#define ALIGNOF(type) ((int)(offsetof(struct {char c; type t;}, t))) 

int main() { 
#define pr(v) std::cout << #v ": " << (v) << std::endl 
    pr(sizeof(long long)); 
    pr(__alignof__(long long)); 
    pr(ALIGNOF(long long)); 
    pr(sizeof(ull)); 
    pr(__alignof__(ull)); 
    pr(ALIGNOF(ull)); 
    pr(sizeof(sll)); 
    pr(__alignof__(sll)); 
    pr(ALIGNOF(sll)); 
}; 

내 시스템 (GCC-4.7, 우분투 12.04, 86)에 출력을 생성 4 바이트 정렬 및 long long이 포함 된 구조체 또는 공용 구조체는 4 바이트 정렬을가집니다.

이것은 gcc의 구현이 __alignof__ 인 버그 또는 적어도 불일치라고 생각됩니다. 그러나 정의의 애매 모호함은 그것이 정말로 버그라는 것을 확신하기 어렵게 만듭니다. It doesn't seem to have been reported.

업데이트 :

내가 총을 점프 할 수 있지만, 난 그냥 bug report를 제출했습니다.

earlier bug report은 "INVALID"로 닫았지만 비슷하지만 구조체 자체의 정렬은 언급하지 않습니다.

업데이트 2 :

내 버그 리포트는 하나 이전의 중복으로 폐쇄되었습니다. 나는 설명을 요구할 것이다.

+0

이 'ALIGNOF()'힌트를 보내 주셔서 감사합니다. – PiotrNycz

+0

그러나 offsetof가 NonPOD와 작동하지 않기 때문에 NonPOD 유형에는이 매크로가 작동하지 않습니다 (http://stackoverflow.com/questions/1129894/why-cant-you-use-offsetof-on-nod-pod-strucutures- in-c). NonPOD 유형에 대한 해답을 알고 계신가요? – PiotrNycz

+0

내 업데이트에 대한 의견을 남길 수 있습니까? '__alignof __ (long long) == 8'이 맞습니다. 그리고'ALIGNOF'로 테스트 한 것은'struct long {struct long} '과 같은 경우 인'struct long'의'long long'을 정렬하는 것입니다. }'. 어쩌면이 버그 보고서에 대한 도움이 될 것입니다. – PiotrNycz