아래 글은 네이버 번역한 것이고요..
정확하진 않아도 의미는 충분히 전달되네요..
그럼 즐공~
+
구조체의 멤버에 가변장 배열(제1부 제 73장참조)를 넣는 일이 있다고 생각합니다.그러나, 그것을 파일에 보존하고 싶을 때, 처리가 조금 귀찮습니다.만약, 그 멤버 자체가 가변장이라면 간단합니다만....
그럼, 이번 요점입니다.
- 구조체의 마지막 멤버를 배열로 해 두면, 그 구조체의 뒤에 있는 데이터를 취급할 수 있다.
- 의도적으로 크게 메모리를 확보해, 그 부분을 배열 멤버의 요소로 온다.
그럼, 말해 봅시다.
그런데, 파일의 정보를 구조체에 넣어 그것을 메모리상에 보존해 둔다고 합니다.간단 때문에, 정보는 패스명(파일의 위치명), 속성, 사이즈의 3개로 합니다.
struct SFileData { char szPath[_MAX_PATH]; // 패스명 unsigned int fAttribute; // 속성 unsigned int nFileSize; // 사이즈 };
그러나, 패스명이라고 하는 것은 최고 문자수 _MAX_PATH 에 이르는 일은 분별없게 않은 것입니다.그 뿐만 아니라, 반에조차 못 미친 것이 대부분입니다.
그렇게 되면,szPath 멤버는 이렇게도 확보하는 것은 메모리가 아깝습니다.그렇다고는 해도,_MAX_PATH 만 필요한 경우도 있으므로, 사이즈를 작게 하는 것도 할 수 없습니다.
그럼, 어떻게 하면 좋은 것일까요? 가변장 배열(제1부 제 73장참조)를 사용하면, 어느 정도 문제는 해결할 것 같습니다.
struct SFileData { char* pszPath; // 패스명 unsigned int nPathLen; // 패스명의 길이 unsigned int fAttribute; // 속성 unsigned int nFileSize; // 사이즈 };
이것으로 좋은 느낌입니다.
그런데, 이것을 파일에 보존도 할 수 있도록(듯이) 하고 싶다고 합니다.이 구조체를 직접 보존하려고 하면,pszPath (은)는 포인터이므로, 거기에는 확보한 메모리에의주소하지만 보존되어 버립니다.그리고, 간신의 확보한 메모리의 내용은 보존되지 않습니다.
그렇게 되면, 먼저 nPathLen 이후의 데이터를 보존해, 다음에 확보한 메모리의 내용을 보존한다고 하는, 2회의 처리가 필요하게 됩니다.전자의 것에서는 그대로 보존할 수 있다는데, 이것은 조금 귀찮습니다.
가변장(이)면서멤버 변수에 포인터를 사용하지 않는다그렇다고 할 수 있으면, 이 문제도 해결합니다만....
거기서, 다음과 같은 거친 기술을 생각할 수 있습니다.
먼저,
struct SFileData { unsigned int nSize; // 구조체의 사이즈 unsigned int fAttribute; // 속성 unsigned int nFileSize; // 사이즈 char szPath[1]; // 패스명 };
그렇다고 하는 구조체를 만듭니다.szPath 의 사이즈는1입니다.
그리고, 이 구조체를 동적으로 확보합니다.이 때, 구조체의 사이즈보다크게 메모리를 확보하면, 그여분으로 확보한 부분은 szPath (을)를 사용하는 것으로 이용할 수 있습니다.
이렇게 하면, 파일에 보존할 때도 nSize 만 파일에 쓰면 좋은 것 같게 되는군요.
왠지 난폭한 방법입니다만, 이 방법은 C/C++에서는 이따금 사용됩니다.이 길이가 바꿀 수 있는 멤버 szPath (을)를,가변장 배열 멤버(이)라고 부릅니다.
잘 사용하는 곳에서는, 비트 맵의 정보를 보관 유지하는 구조체 BITMAPINFO 하지만 그렇게 되고 있습니다.
256색비트 맵은 색을 0~255까지의 번호로 취급합니다.그리고, 그 번호에 대응하는 색 정보를 이 BITMAPINFO 구조체 로 유지해 둡니다.이 색 정보를 「팔레트」라고 부릅니다.
이것은 16색비트 맵에서도 같습니다.그러나, 16색과 256색과는 팔레트의 수는 다릅니다.그 말은, 이 멤버는 가변장이라면 편리하네요.
이것이 풀 컬러가 되면, 팔레트를 사용하지 않습니다.그래서, 이 멤버는 사용하지 않는다고 하는 것이 됩니다.이것으로부터 알 수 있듯이, 요소수는 1이 아니면 안 되는 것은 아닙니다.
그럼, 실제로 SFileData 구조체를 사용해 봅시다.
프로그램 | |
---|---|
// Sizing1.cpp #include <iostream.h> #include <string.h> #include <memory.h> #include <stdio.h> #include <stdlib.h> #include <stddef.h> #define numof(array) (sizeof (array) / sizeof *(array)) struct SFileData { unsigned int nSize; // 구조체의 사이즈 unsigned int fAttribute; // 속성 unsigned int nFileSize; // 사이즈 char szPath[1]; // 패스명 }; void Init(); // 초기화 bool Input(); // 입력 void Output(); // 출력 void Delete(); // 메모리의 해방 // 파일의 데이터 SFileData* g_apfdata[100]; // 데이터수 int g_nData = 0; int main() { Init(); while(Input()); Output(); Delete(); return 0; } // 초기화 // 일단 누르포인타의 값이 0이 아닐 때를 위해서... void Init() { int i; for(i = 0; i < numof(g_apfdata); i++) g_apfdata[i] = NULL; } // 입력 bool Input() { if(g_nData == numof(g_apfdata)) return false; // 영역은 동적 확보하지 않으면 안 되는 것은 아닙니다 char bufFData[sizeof (SFileData) + _MAX_PATH]; SFileData* pfdTemp = (SFileData*)bufFData; char* pbufTemp; cout << "패스명, 속성, 사이즈를 입력해 주세요" << endl; cin >> pfdTemp->szPath >> pfdTemp->fAttribute >> pfdTemp->nFileSize; if(pfdTemp->nFileSize == 0) return false; // 사이즈는 szPath 까지의 아르바이트수+문자열의 길이+1 // 마지막 1은 누르캐라크타의 분입니다 pfdTemp->nSize = offsetof(SFileData, szPath) + strlen(pfdTemp->szPath) + 1; // 메모리의 확보 pbufTemp = new char[pfdTemp->nSize]; if(pbufTemp == NULL) return false; g_apfdata[g_nData] = (SFileData*)pbufTemp; // 데이터세트 memcpy(g_apfdata[g_nData], pfdTemp, pfdTemp->nSize); g_nData++; return true; } // 출력 void Output() { FILE* pfile; int i; pfile = fopen("Sizing1.dat", "wb"); for(i = 0; i < g_nData; i++) fwrite(g_apfdata[i], 1, g_apfdata[i]->nSize, pfile); fclose(pfile); } // 메모리의 해방 void Delete() { int i; for(i = 0; i < g_nData; i++) delete [] (char*)g_apfdata[i]; } | |
실행 결과예 | |
패스명, 속성, 사이즈를 입력해 주세요 C:\Program\Algorithms.html 32 412315 패스명, 속성, 사이즈를 입력해 주세요 C:\Program\Registry\데스크탑 아이콘의 비표시법.txt 32 155 패스명, 속성, 사이즈를 입력해 주세요 C:\Program\Program.ico 32 3638 패스명, 속성, 사이즈를 입력해 주세요 C:\Program\카셋트 늦추어\slide.html 32 6380 패스명, 속성, 사이즈를 입력해 주세요 0 0 0 | |
Sizing1.dat | |
16진치 | 문자 |
27 00 00 00 20 00 00 00 9B 4A 06 00 43 3A 3A 5C 72 6F 67 72 61 6D 5C 41 6C 67 6F 72 69 74 68 6D 73 2E 68 74 6D 6C 00 43 00 00 00 20 00 00 00 9b 00 00 00 43 3A 5C 50 72 6F 67 72 61 6D 5C 52 65 67 69 73 74 72 79 5C 83 66 83 58 83 4E 83 67 83 62 83 76 83 41 83 43 83 52 83 93 82 CC 94 F1 95 5C 8E A6 96 40 2E 74 78 74 00 23 00 00 00 20 00 00 00 36 0E 00 00 43 3A 5C 50 72 6F 67 72 61 6D 5C 50 72 6F 67 72 61 6D 2E 69 63 6F 00 31 00 00 00 20 00 00 00 EC 18 00 00 43 3A 5C 50 72 6F 67 72 61 6D 5C 83 4A 83 5A 83 62 83 67 82 B8 82 E7 82 B5 5C 73 6C 69 64 65 2E 68 74 6D 6C 00 |
'... ....J..C:\P rogram\Algorithm s.html.C... .... ...C:\Program\Re gistry\데스크특 프아이콘의 비표 시법.txt.#... . ..6...C:\Program \Program.ico.1.. . .......C:\Prog ram\카셋트않고들 해\slide.html. |
이와 같이, 가변장 배열 멤버를 가지는 구조체는직접 선언하지 않습니다.즉,
SFileData fdata;
(와)과 같이는 하지 않습니다.단지, 마지막 멤버를 사용하지 않을 때는, 이와 같이 해도 우선 실제 손해는 없습니다.
이번은 이것으로 마지막입니다.이번 프로그램은 조금 깁니다만, 침착해 해석해 봐 주세요.
그럼, 이번 요점입니다.
- 구조체의 마지막 멤버를 배열로 해 두면, 그 구조체의 뒤에 있는 데이터를 취급할 수 있다.
- 의도적으로 크게 메모리를 확보해, 그 부분을 배열 멤버의 요소로 온다.
그러면, 또.