익명 구조체는 48.3 https://dojang.io/mod/page/view.php?id=410 에서
typedef와 별칭을 통해서 사용할 수 있다고 배웠습니다. 그러나
55.3 https://dojang.io/mod/page/view.php?id=464 이처럼 구조체/공용체 안에서 정의하는 익명 구조체/공용체는 typedef도, 별칭도 없이 선언이 가능합니다. 왜 이런지 알고싶습니다!
2. 리틀 엔디언
54.2 https://dojang.io/mod/page/view.php?id=455에서 리틀 엔디언은 저장할 때 작은 자리수부터 뒤집어서 저장하고, 출력할 때는 다시 또 뒤집어서 출력한다고 하였습니다.(1바이트 단위로)
하지만 55.7 https://dojang.io/mod/page/view.php?id=468에선 저장할 때는 뒤집었지만, 출력시에 순서는 다릅니다.
제가 고민해 보았을 땐,54.2에선 int로 묶어서 2자리씩 4개를 한번에 저장해서 다시 원래 순서로 출력 할 수 있지만 55.7에선 char 단위로 2자리씩 1개씩을 저장해서 생긴 차이로 생각되는데 정확히 이해가 되질 않습니다... 혹시 설명해주신다면 감사하겠습니다!
의미없는 것에 의미를 부여하면서 깊이 이해한다고 생각하지 않는 게 좋습니다. 그냥 이렇게 익명으로 선언할 수 있다고 언어 제작자가 허용하기로 했을 뿐입니다.
여기에 사람들이 의미를 부여해서 해석하려고 할 수는 있겠지만요. 이에 대한 우화 같은 소설로는 <깊이에의 강요>라는 작품이 있겠네요.
#include <stdio.h>
struct { int a; };
int main(void) {
printf("Hello World!\n");
return 0;
}
이런 코드도 잘 컴파일됩니다. 구조체에 이름도 없고, 별칭도 없으니 이걸 참조할 방법이 없으니 저 구조체로 데이터 타입을 선언할 방법이 없겠네요.
구조체 안에 익명으로 선언하면 바깥에 있는 구조체 이름을 통해서 내부에 선언한 익명 구조체에도 접근할 수 있으니까 문제가 되지 않습니다. 여기서 문제란 문법적인 문제가 아니라 코드로 접근할 수 있으냐의 문제겠지요.
struct DeviceOption {
union {
unsigned long long option;
struct {
unsigned char boot[4];
unsigned char interrupt[2];
unsigned char bus[2];
};
};
};
자료 구조로 보면
boot0,1,2,3, inter0, 1, bus0, 1 순서입니다.
opt.boot[1] = 0x02;
opt.boot[2] = 0x03;
opt.boot[3] = 0x04;
opt.interrupt[0] = 0x05;
opt.interrupt[1] = 0x06;
opt.bus[0] = 0x07;
opt.bus[1] = 0x11;
2번 질문에서 리틀 엔디안은 확실히 뒤집어서 저장함을 이해했습니다.(char은 상관없이)
제가 궁금한 것은 출력할 때 다시 뒤집어서 입력할 당시의 순서로 보여지게 출력해주는 경우(54.2)와 그냥 뒤집어서 저장한 그대로 출력하는 경우(55.7)로 나뉘는 이유가 궁금합니다.
보여지는 결과 때문에 헷갈린 것 같습니다.
#include <stdio.h>
union Data { // 공용체 정의
char c1[4];
short num1;
int num2;
};
int main()
{
union Data d1; // 공용체 변수 선언
d1.c1[0] = 0x01;
d1.c1[1] = 0x02;
d1.c1[2] = 0x03;
d1.c1[3] = 0x04;
union Data d2;
d2.num2 = 0x01020304;
//d1.num2 = 0x12345678; // 리틀 엔디언에서는 메모리에 저장될 때 78 56 34 12로 저장됨
printf("0x%x\n", d1.num2); // 0x12345678: 4바이트 전체 값 출력
printf("0x%x\n", d1.num1); // 0x5678: 앞의 2바이트 값만 출력
printf("0x%x\n", d1); // 0x5678: 앞의 2바이트 값만 출력
printf("0x%x\n", d2); // 0x5678: 앞의 2바이트 값만 출력
printf("%d\n", sizeof(d1)); // 4: 공용체의 전체 크기는 가장 큰 자료형의 크기
return 0;
}
d1, d2를 만들어서 테스트하면 됩니다.
0x4030201 0x201 0x4030201 0x1020304 4
시각화해서 보면 됩니다.
array의 순서를 보면 0 1 2 3으로 되어 있습니다.
d2.num2 = 0x01020304로 할당하면 메모리에 리틀 엔디언으로 저장되니까 04030201 순서로 저장됩니다.
04가 0번째 주소이고, 낮은쪽 비트입니다. LSB부터 저장하는 건데, 이런 건 <컴퓨터 구조> 관련 전공서를 보는 게 좋습니다. 컴공 전공이면 어차피 전공 필수일 겁니다. 아니면 패터슨이나 스털링 책을 보면 됩니다.
d1.c1[0] = 0x01처럼 직접 번지수를 지정해서 넣으면 지정해서 넣었기 때문에 0x01020304가 됩니다. 단지 그뿐입니다.