C에서 구조체를 선언하지 않고 멤버의 배열크기를 알아내고 싶습니다.
글쓴이: raidol / 작성시간: 토, 2015/05/23 - 1:58오후
안녕하세요,
struct TEST{
int code;
char result[128];
int* err;
};
예를들어 위와같은 구조체 TEST가 있는데요.,
여기서 result 멤버의 sizeof 결과를 가져오고 싶습니다.
struct TEST test; 선언하고 sizeof(test.result); 하면 쉽겠지만,
선언하지 않고 가져올 수 있는 방법 없을까요? sizeof((struct TEST).result); 이건 뭐 당연히 안될테고..
방법이 없다면 임시변수 선언을 할 수밖에 없지만 방법이 없는건지 제가 모르는건지..-_-a
Forums:
답변
1. offsetof 매크로를 이용합니다.
다만 이 경우 구조체의 패딩에 관한 문제가 있어서,
4바이트 경계로 패딩이 설정되어있으면 char 형식 멤버의 크기를 4바이트로 뱉을 수 있다는 점 때문에
그렇게 신뢰할 방법은 아닙니다.
2. 구조체의 전체 크기에서 나머지 두 멤버의 크기를 뺍니다.
이 또한 패딩 문제가 해결된 것이 아니기 때문에 신뢰할 수 없습니다.
3. result 멤버의 크기를 #define을 이용하여 정의하고 계산한 값을 반환합니다.
이해하기 쉽고 언제나 타당합니다.
L. 그냥 임시 변수를 만들어서 씁니다.
당연히 언제나 타당합니다.
-----
The C Programming Language는 sizeof 연산자 뒤에 가능한 요소가 다음의 두 가지밖에 없다고 설명하고 있습니다. (번역본 p.330)
sizeof unary-expression
sizeof ( type-name )
즉 sizeof를 사용하려면 형식 이름이나 단항식만 가능한데 구조체의 멤버 이름은 형식 이름은 아니고,
구조체 변수를 정의하지 않은 상태에서 멤버 이름으로만 단항식을 구성할 수도 없으니 별도의 방법을 써야 합니다.
컴파일러가 확장해서 지원하지 않는 한, 문법적으로 이걸 지원하는 키워드는 없다는 것이 제 결론입니다.
저는 이렇게 생각했습니다.
sizeof((struct
sizeof((struct TEST*)NULL)->result) 또는 sizeof(((struct TEST){}).result) 하면 됩니다.
전자는 NULL 포인터를 디레퍼런싱하지만 sizeof는 compile 타임에 평가되므로 실제로 실행되는 식이 아니기 때문에 실행시에 죽는 일은 없습니다.
NULL이라는 값을 썼지만 실제로 실행되지 않기 때문에 아무 정수나 와도 상관없습니다.
후자는 인스턴스를 생성하는 식이지만 마찬가지로 실제로 실행되는 식이 아니므로 실제로 객체를 만들지는 않습니다.
질문 있습니다.
1. sizeof (((struct TEST *)NULL)->result);와 같이 쓸 수 있다는 생각은 못 했네요. 놀랐습니다.
2. 테스트를 위해 다음과 같이 코드를 작성해보았습니다.
다른 온라인 컴파일러에서는 모두 정상적으로 동작하는 반면, Visual Studio에서 빌드한 결과, size1에는 이상이 없지만 size2의 경우 C2059 구문 오류를 뱉으며 빌드에 실패했습니다.
두 번째 구문은 표준에 의하면 언제나 타당한 구문인가요?
그러니까, 이 경우는 Visual Studio가 C 컴파일러 구현을 온전히 하지 못한 것일까요?
저는 이렇게 생각했습니다.
compound literal이라고 C99에서 추가된
compound literal이라고 C99에서 추가된 문법입니다. msvc의 지원이 어떤지는 모르겠네요.
답변 확인했습니다.
입문서랑 TCPL만으로 공부했더니 바뀐 C 문법은 제가 정말 모르는군요.
C99도 새롭게 공부해봐야겠습니다.
저는 이렇게 생각했습니다.
감사합니다.
답변주신 두분께 감사드립니다. 방금 컴파일 해봤는데 잘됩니다.^^
댓글 달기