구름 안개 속의 sizeof (구조체)
struct{
long a;
char b;
short c;
char d;
}y;
y 안에:
나는 이런 코드를 썼다:
struct y temp;
printf ("%d \ n% d \ n% d \ n% d \ n", & Temp.a,& Temp.b,& Temp.c,& Temp.d);
결과:
124544
124548
12455
124522
이 위는 주소이고 y 안에 있는 a,b ,c 입니다 //124544
char b; //124548
short c; //12455
char d; //124552
}y; < P > 바이트 정렬을 감안하면 내가 위에서 준 답안을 보면
a 가 4 개, B 가 1 개라는 것을 쉽게 이해할 수 있다. 하지만 C 는 12455 부터 시작한다. 즉, 비어 있는 주소는 124549 가 B 뒤에 보충되고 부족한 것은 으로 채워진다. (알버트 아인슈타인, Northern Exposure (미국 TV 드라마), Northern Exposure (미국 TV 드라마) 4 바이트를 보충하기에는 부족합니다. 그러면 D 가 4 바이트
를 차지하므로 1 * * * 는 12 바이트
struct{
long a; 입니다. //4
short b; //2
char d; //1
int c; //4
}yy;
정렬 고려:
4+4+4=12 b 는 2 개, d 는 1 개, 부족한 것은 보완해야 하므로 BD 1 * * * 은 4 개
struct {
를 차지합니다
short b;
int c;
char d;
}yyy;
a=4; B=2; C =4 d = 1
여기서 a 는 4 개, b 는 2 개, 4 바이트 정렬은 2 개, c 는 4 개
short b;
long c;
char d;
char e;
}yyyy;
a 뒤에 하나를 보충하고 b 1 * * * 은 4 개, c 4 개, de 1 * * * 은 4 개
4+4+4 = 12
struct {
를 차지합니다
short b;
long c;
char d;
char e;
}yyyyy;
a=4 b 가 2 개를 차지하면 2 개, C 가 4 개, de 가 4 개
4+4+4+4=16
제안도 있습니다.
# pragmapack (push)
# pragmapack (1)//여기서 괄호 안에 1
가 있습니다
char b;
short c;
char d;
}y;
#pragma pack(pop)
그렇다면 현재 크기는 어떻게 되나요? 대답은 4+1+2+1=8 입니다. 1 바이트로 정렬됩니다.
왜? 아래 자료를 보세요.
다음은 자료입니다.
typedef union // 정의 * * * 용체
{
long I; //long 4 바이트
int k[5]; //int 4 바이트 4*5 = 2
char c; //char 1 바이트:
}DATE; < P > 위의 구조는 연합이다. 연합된 구조는 중간에 가장 큰 것을 취하면 된다. 그들이 공용이기 때문에 가장 큰 공간을 찾으면 작은 것도 큰 안에 담을 수 있고, 작은 것을 취하면 큰 것은 작은 안에 담을 수 없다.
분석: 위의 가장 큰 것은 2
struct date // 구조 정의
{
int cat; //int 4 바이트
DATE cow; //DATE 통합 클러스터: 2 바이트
double dog; //double 8 바이트
}too;
// 위의 구조체는 연합이 아니기 때문에: 4+2+8 = 32
여야 하므로 답은 2+32 =52
입니다. 저는 개인적으로 구조에 대해 알고 싶다면 이 일이 충분하지 않다고 생각합니다. //int 4 바이트
DATE cow; //DATE 통합 클러스터: 2 바이트
double dog; //double 8 바이트
char a;
}too; < P > 정렬을 고려한다면: < P > 위의 구조에 char a 를 추가했는데, 지금 구조가 얼마나 큰가요? 당신은 53,54,56 이라고 하는데, 사실 다 맞나요? 왜 그럴까요? < P > 이것은 당신의 기계가 어떤 식으로 정렬되느냐에 달려 있기 때문입니다.
다음 코드 섹션을 보십시오.
# pragmapack (push)
# pragmapack (n)
struct date//구조 정의
//int 4 바이트
DATE cow; //DATE 통합 클러스터: 2 바이트
double dog; //double 8 바이트
char a;
}too;
#pragma pack(pop)
이 구조의 경우: 정렬은 #pragma pack(n) 의 n 값에 따라 달라집니다. n=4 인 경우 위의 구조는 56 입니다 기본값은 4 바이트이지만 임베디드 영역에서는 일반적으로 1 바이트로 정렬됩니다. < P > 다음은 이해를 깊게하기 위해: 정보를 좀 드리겠습니다. ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ
# pragmapack (pop)
intmain ()
{
printf ("%d", sizeof (struct data) /* struct date 구조가 차지하는 공간의 크기와 DATE max 구조가 차지하는 공간의 크기에 해당합니다. */
리턴 ;
}
이것은 초보자가 가장 많이 묻는 질문이므로 여기에 필묵을 많이 써야 한다. 먼저 *
구조 * 본체:
struct S1
{
char c;
int I;
};
q *sizeof*(s1)* 등 * 얼마나 됩니까? 똑똑한 네가 생각하기 시작했다. char 는 1 바이트, int 는 4 자 < P > 를 차지한다면, < P > 를 더하면 5 가 될 것이다. 그렇습니까? 너는 너의 기계에서 해본 적이 있니? 네가 맞을지도 모르지만, 아마 네가 < P > 가 틀렸을 거야! V
C6 의 기본 설정은 8 입니다.
Why? 왜 다친 사람은 항상 나야?
제발 * 아니요 * 좌절하려면 *sizeof* 의 정의-* sizeof * 의 결과 * 등 * 개체
또는 유형이 차지하는
의 메모리 바이트 수를 잘 생각해 봅시다 < P > 위의 변수를 정의한 후 중단점을 추가하고 프로그램을 실행하고 S1 이 있는 메모리를 관찰하면 무엇을 발견할 수 있습니까?
제 VC6. 의 경우 S1 의 주소는 x12FF78 이며, 그 데이터 내용은 다음과 같습니다.
12FF78: 61 CC CC CC FF FF FF FF
무엇을 발견했습니까? 왜 중간에 3 바이트 CC 가 섞여 있나요? MSDN 의 지침을 보십시오:
when applied to a structure type or variable, * sizeof * returns the
actual size,
white 중요한 화제가 나타났다.
바이트 정렬이 필요한 이유는 무엇입니까? 컴퓨터 구성 원리는 이렇게 하면 컴퓨터 취수 속도 < P > 를 가속화하는 데 도움이 된다는 것을 가르쳐 준다. 그렇지 않으면 < P > 는 지시주기를 더 많이 써야 한다. 이를 위해 컴파일러는 기본적으로 * 구조 * 본체를 처리하고 (* 실제 * 의 다른 곳에 있는 < P > 측의 데이터 변화 < P > 양도 마찬가지임), 너비가 2 인 기본 데이터 유형 (short* 등 *) 을 2 로 나눌 수 있는 주소 < P > 에 배치합니다 이렇게 하면 두 < P > 수 중간에 < P > 가 패딩 바이트를 추가해야 할 수 있으므로 전체 * 구조 * 본체의 *sizeof* 값이 증가합니다.
S1 에서 char 와 int 의 위치를 바꿔 봅시다.
struct S2
{
int I;
char c;
};
*sizeof*(S2) 의 결과가 얼마인지, 어떻게 8 인지 보세요. 메모리를 다시 보면 원래 멤버 C 뒤에는 여전히
3 개의 필러 < P > 섹션이 있습니다. 왜 그럴까요? 조급해하지 말고 아래에 법칙을 총결하시오. < P > 바이트 정렬의 세부 사항 * 은 * 컴파일러 구현과 관련이 있지만 일반적으로
1) * 구조 * 본문 변수의 첫 번째 주소는 가장 넓은 기본 유형 멤버의 크기로 나눌 수 있습니다.
2) * 구조 * 본문 각 구성원의 * 구조 * 본문 첫 번째 주소로부터의 오프셋 (offset) 은 멤버 크기의
정수 배수입니다.
가 필요한 경우 컴파일러가 멤버 사이에 패딩 바이트 (internal adding) 를 추가합니다
3) * 구조 * 본체의 총 크기는 * 구조 * 본체의 가장 넓은 기준 유형 멤버 크기의 정수 배수이며,
를 컴파일해야 하는 경우 마지막
멤버 뒤에 패딩 바이트 (trailing padding) 가 추가됩니다.
위 지침에 대해 몇 가지 설명이 필요합니다.
1) 앞 * 아니오 * 는 * 구조 * 본체 구성원의 주소가 크기의 정수 배수라는 것을 의미합니다. 어떻게 오프셋
에 대해 이야기 할 수 있습니까? 점
1 이 존재하기 때문에 우리는 구성원의 오프셋만 고려할 수 있어 쉽게 생각할 수 있다. (데이비드 아셀, Northern Exposure (미국 TV 드라마), 남녀명언) 왜 그런지 생각해 보세요.
* fabric * body 의 첫 번째 주소로부터 * fabric * body 구성원의 오프셋은 매크로 offsetof () 를 통해 얻을 수 있으며,
이 매크로는
stddef.h 에도 다음과 같이 정의됩니다.
# (((s *))-> M)
예를 들어,
size _ t pos = offset of (S2, c); // pos* 등 * 4
2) 기준 유형은 앞서 언급한 char, short, int, float, double 과 같은 내장형 데이터
유형,
여기서 말하는 "을 의미합니다 * 구조 * 본체의 멤버는 복합
유형일 수 있고
보다 다른 * 구조 * 본체일 수 있으므로 가장 넓은 기준 유형 멤버를 찾을 때 복합 유형 멤버의
하위 멤버,
및 * 아니오 * 를 포함해야 합니다 그러나 복합 유형 멤버의 간격띄우기 위치를 결정할 때는
복합 유형
을 전체적으로 취급합니다.
여기에 서술하면 좀 어색하고, 생각만 해도 좀 긁힌 것 같은데, 예를 들어 보자. (구체적인 수치
는 여전히 VC
6 을 예로 들어 나중에 * 아니오 * 를 다시 설명하지 않는다.):
struct S3
S1 s;
char c2
};
S1 의 가장 넓은 단순 멤버 유형은 int 이고, S3 은 가장 넓은 단순 유형 멤버를 고려할 때 S1 을
로' 분리' 하므로
S3 의 가장 넓은 단순 유형은 int 이므로 S3 을 통해 정의된 변수의 저장 공간 첫 번째 주소는 4 로 반올림해야 합니다
c1 의 오프셋은 , s 의 오프셋입니까? 이때 S 는 * 구조 * 본체 변수로도 앞의 < P > 면 세 가지 기준 < P > 을 만족시키므로 크기가 8 이고 오프셋이 4 이고 C1 과 S 사이에 3 개의 패딩 바이트가 필요합니다. C2 와 S 사이에는 * 아니오
* 가 필요합니다.