2011년7월5일_숙제_배열을 가리키는 구조체(struct)로 일정 양식(format)에 맞게 엑세스
● 선생님께서 불러주신대로 친 소스코드
1: //2011년7월5일_숙제_배열을 가리키는 구조체(struct)로 일정 양식(format)에 맞게 엑세스
2: #include <stdio.h>
3:
4: typedef struct
5: {
6: int a;
7: int b;
8: int c;
9: } EMB;
10:
11: int main()
12: {
13: int array[6];
14: EMB *stp;
15: unsigned char *ucp;
16:
17: stp = (EMB *)array;
18: ucp = (unsigned char *)array;
19:
20: *ucp = 0x64;
21: ++ucp;
22: *ucp = 0x00;
23: ++ucp;
24: *ucp = 0x00;
25: ++ucp;
26: *ucp = 0x00;
27:
28: ++ucp;
29: *ucp = 0x63;
30: ++ucp;
31: *ucp = 0x00;
32: ++ucp;
33: *ucp = 0x00;
34: ++ucp;
35: *ucp = 0x00;
36:
37: ++ucp;
38: *ucp = 0x62;
39: ++ucp;
40: *ucp = 0x00;
41: ++ucp;
42: *ucp = 0x00;
43: ++ucp;
44: *ucp = 0x00;
45:
46: ++ucp;
47: *ucp = 0x61;
48: ++ucp;
49: *ucp = 0x00;
50: ++ucp;
51: *ucp = 0x00;
52: ++ucp;
53: *ucp = 0x00;
54:
55: stp = (EMB *)&array[1];
56:
57: printf("array[0] %d\n", array[0]);
58: printf("array[1] %d\n", array[1]);
59: printf("array[2] %d\n", array[2]);
60: printf("stp->a %d\n", stp->a);
61: printf("stp->b %d\n", stp->b);
62: printf("stp->c %d\n", stp->c);
63:
64: ucp = (unsigned char *)array;
65: ++ucp;
66: stp = (EMB *)ucp;
67:
68: printf("stp->a %d\n", stp->a);
69: printf("stp->b %d\n", stp->b);
70: printf("stp->c %d\n", stp->c);
71: return 0;
72: }
17행에서 구조체포인터 stp는 array의 시작을 가리키고,
18행에서 unsigned char 포인터 ucp도 array의 시작을 가리킨다.
*ucp로 array배열에 순서대로 0x64, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00 을 넣는다.
메모리(stack)는 아래와 같이 된다.
● 메모리상태
일반변수가 쌓이는 순서와 달리 배열의 인덱스들은 거꾸로 되어 있다는 것에 유의하자.
인덱스가 커질수록 인입함수의 EBP의 값이 저장된 곳으로 돌진한다.
● 소스코드 분석 들어갑니다
1: stp = (EMB *)array;
2: ucp = (unsigned char *)array;
한 마리의 암컷사자를 두고 두 마리의 숫사자가 대치하고 있는 상황과 유사하다.
EMB구조체 포인터변수 stp와 unsigned char 포인터변수 ucp가 모두 array의 주소를 갖고 있다.
1: stp = (EMB *)&array[1];
2:
3: printf("array[0] %d\n", array[0]);
4: printf("array[1] %d\n", array[1]);
5: printf("array[2] %d\n", array[2]);
6: printf("stp->a %d\n", stp->a);
7: printf("stp->b %d\n", stp->b);
8: printf("stp->c %d\n", stp->c);
stp->b를 읽으면 stp가 가리키는 곳의 5Bytes째(a크기 + 1) 부터 읽기 시작하여 b의 크기만큼 읽어 들이게 된다. (array[2]의 값)
stp->c를 읽으면 stp가 가리키는 곳의 9Bytes째(a와 b의 크기 +1) 부터 읽기 시작하여 c의 크기만큼 읽어 들이게 된다. (array[2]의 값)
1: ucp = (unsigned char *)array;
2: ++ucp;
3: stp = (EMB *)ucp;
4:
5: printf("stp->a %d\n", stp->a);
6: printf("stp->b %d\n", stp->b);
7: printf("stp->c %d\n", stp->c);
다시 ucp의 값을 array배열의 시작주소로 초기화한 뒤에,
ucp의 값을 1증가시키고 stp가 ucp를 가리키게 하면,
엄청나게 큰 값이 나온다. 왜 그런지 아래의 메모리상태도를 보고 분석하자.
마치 구조체 EMB를 슬라이드로 하여 array를 투영하는 것과 같다.
%d형식지정자로 출력하면 값확인이 어려우니..%08X형식지정자로 16진수값을 확인하는 것이 좋다.
1: printf("stp->a %08X\n", stp->a);
2: printf("stp->b %08X\n", stp->b);
3: printf("stp->c %08X\n", stp->c);
big endian과 little endian개념이 없는 분들은 보고 잘 이해가 안되 혼란스러우실 겁니다.
의문이 있으면 댓글 남겨주세요.
이렇게 구조체를 선언하지 않고 구조체를 가리키는 포인터변수만 선언하여 1차원배열(버퍼)을 일정양식에 맞게 엑세스하고 싶을 때,
사용하면 좋겠다. hexaview프로젝트에 적용한다면 파일포맷에 맞게 값을 읽고 쓸 수 있을 것이다.
예를 들어, bmp파일의 경우 헤더부분에 RAW DATA의 크기가 있는데 그 부분을 읽는다고 포인터를 이동하는게 아니라.
구조체의 값만 읽으면 끝나니 매우 편리한 방법이라고 할 수 있겠다.
잇힝!
'내장형하드웨어 > 일일보고서' 카테고리의 다른 글
2011년7월6일_함수를 인수받고 함수를 반환하는 괴상한 함수와 그 함수를 가리키는 함수포인터 (0) | 2011.07.06 |
---|---|
2011년7월5일_함수를 반환하는 함수와 함수를 반환하는 함수의 함수포인터 (0) | 2011.07.06 |
2011년7월4일_배열의 주소와 값의 표기법, 함수포인터배열, TCP/IP소켓통신흐름, 접속한 클라이언트의 IP주소알아내기, 함수포인터의 반환형찾기 (2) | 2011.07.04 |
2011년6월30일_파일입출력시 바이너리모드와 텍스트모드에 관한 고찰 (0) | 2011.07.01 |
2011년6월29일_예제p11-10, 구조체(메모리) → 파일로 기록하여 RAW DATA분석 (0) | 2011.06.30 |