구조체 alignment 에 관련해서 질문드립니다.

purenix의 이미지

안녕하세요. 항상 도움 많이 얻어가는 사람입니다.
이번에도 꼭 도움 좀 부탁드립니다.

이번에 공무원을 준비하면서 문제를 풀어보고 있는데 다음과 같은 문제가 있습니다.

struct st {
int a;
union {
int b;
long c;
};
};

여기서 int 는 4byte, long 은 8byte 라고 가정했을 때,
sizeof(st) 를 하게 되면 결과값이 16이 나오던데 이게 맞는 것인지요?

문제 자체에 alignment size 에 대한 언급은 없습니다.

처음에는 alignment 값이 시스템의 word size 에 맞춰서 결정되는 줄 알았는데
다른 글들을 찾아보니 컴파일러가 임의로 결정할 수도 있더군요.

질문1. alignment size 결정에 word size 와 컴파일러 둘 다 영향을 미칠 수 있는지요?

질문2. 위 문제에서 답이 12가 될 가능성은 없는 걸까요?

음.. 이 문제에서는 단순히 alignment size 를 가장 큰 자료형의 크기에 맞추는게 맞는 걸까요...
그렇게 하기엔 뭔가 찝찝해서 이렇게 질문 올립니다.

답변 꼭 부탁드리겠습니다.
감사합니다.

익명 사용자의 이미지

따라서 우리는 늘 구조체 맴버변수 사이에 빈공간이 들어갈수도 있고
그 크기도 제멋대로라는걸 감안해야 합니다.
implementation-defined도 아니고 unspecfied 인 값이라서 컴파일러가 명시해야 할 의무조차도 없습니다.

또한 구조체 자체의 주소값이 가질 수 있는 정렬 제한도 정해진바 없습니다.
대체로 시스템의 특성을 컴파일러도 따라가겠지만
반드시 그래야 하는 의무가 있는건 아닙니다.

답변1. 원칙적으로는 모든게 다 영향을 미칠 수도, 안미칠 수도 있습니다. 이걸 감안하고 프로그램을 짜는게 현명합니다.

답변2. 원칙적으로는 안될꺼 없지요. gcc에서 #pragma pack(push, 1) 만 추가해도 결과값이 12가 될 겁니다.

purenix의 이미지

이 문제는 그냥 잊어버려야겠습니다.

jick의 이미지

하나의 시스템에서 A라는 컴파일러로 컴파일한 소스가 B라는 컴파일러로 컴파일한 라이브러리와 호환되는 것은 보장을 해줘야죠. 그렇기 때문에 (제가 아는 한은) 구조체 정렬 방법이 ABI 규격에 포함되는 걸로 알고 있습니다.

즉 같은 시스템 안에서라면 항상 같은 방식으로 정렬이 되는 것이 보장됩니다.

(물론 #pragma pack 같은 걸 쓰기 시작하면 더 이상 그런 보장 같은 건 없죠.)

익명 사용자의 이미지

추가적으로 ABI같은 별개의 약속을 적용한다면, 그 약속 안에서 호환성이나 동작의 확실성이 보장될 수도 있겠죠.
그러나 ISO/IEC 9899:1999 안에서 Unspecified냐 아니냐를 따진다면, Unspecified가 맞습니다.

6.2.6.1.6.

When a value is stored in an object of structure or union type, including in a member
object, the bytes of the object representation that correspond to any padding bytes take
unspecified values.

J.1 Unspecified behavior

- The value of padding bytes when storing values in structures or unions(6.2.6.1)

jick의 이미지

(냉무)

익명 사용자의 이미지

제가 잘못 알고 있었습니다. 구조체 안의 padding bytes의 길이는 implementation-defined가 맞습니다.

6.7.2.1.11

Each non-bit-field member of a structure or union object is aligned in an implementation-defined manner appropriate to its type.

그러나 다음 두줄은 참이 아닙니다.

> 하나의 시스템에서 A라는 컴파일러로 컴파일한 소스가 B라는 컴파일러로 컴파일한 라이브러리와 호환되는 것은 보장을 해줘야죠.
> 즉 같은 시스템 안에서라면 항상 같은 방식으로 정렬이 되는 것이 보장됩니다.

implementation-defined라는건 어떻게 동작하는지 밝힐 의무가 있다는 것이지, 시스템 따라가라는 의미는 아닙니다.

> 그 크기도 제멋대로라는걸 감안해야 합니다.
> implementation-defined도 아니고 unspecfied 인 값이라서 컴파일러가 명시해야 할 의무조차도 없습니다.

제가 말한 부분 중에서 요 부분이 틀렸습니다.
엄밀하게 말하면 구조체 패딩에 대해서는 뭔가 규칙이 있어야 하고, 그 규칙을 명시해야 합니다.

gcc의 예를 들자면...

http://gcc.gnu.org/onlinedocs/gcc-4.6.3/gcc/Structures-unions-enumerations-and-bit_002dfields-implementation.html#Structures-unions-enumerations-and-bit_002dfields-implementation

...The alignment of non-bit-field members of structures (C90 6.5.2.1, C99 6.7.2.1).
Determined by ABI...

4 C Implementation-defined behavior 항목에서 어떻게 동작할지를 명시하고 있네요.

MS나 ARM 같은 데서도 아마 문서를 뒤져보면 명시를 해놓은 부분이 있을 것 같군요.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.