[질문]공용체안의 구조체 값을 생성할때

elanoia의 이미지

union A{
		struct {
				unsigned int a ; 
				unsigned int b ;
		} Int0;
		struct {
				unsigned int c ;
				unsigned int d ;
		}Int1;
		int e;
};

#define INT0(a,b) { {a,b}}
#define INT1(c,d) { Int1:{c,d}}

union A aa[]= {
		INT0(1,2),
		INT1(3,2)
};


int main()
{
  int i;

  for(i=0; i<2; i++){
		  printf("%d %d %d %d %d\n", aa[i].Int0.a, aa[i].Int0.b, aa[i].Int1.c, aa[i].Int1.d, aa[i].e);
  }

  return 0;
}

위와 같은 코드를 작성하였습니다. 컴파일 후 결과를 보면, 다음과 같이 나옵니다.

1 2 1 2 1
3 2 3 2 3

질문 1 :
여기서 제가 임의적으로 초기화 하지 않은 변수들에 대한 값들(aa[0].Int0.c, d, e, aa[1].Int0.a, b, e )이 의미있는 값들인지 쓰레기 값인지 알고 싶습니다. 즉, 어떠한 규칙에 의해 생성되는 것인지, 마구잡이식의 쓰레기 값인지 말이죠. 여러번 컴파일 해봐도 같은 값이 나옵니다.

질문 2:
#define INT1(c,d) { Int1:{c,d}} 과 같이 Int1에 접근을 했는데 다른 방법으로로 접근이 가능하거나, 생성시 초기화가 가능한지요? gcc가 아닌 다른 다른 컴파일러에서는 이런 신택스가 안 통해서 고치고 싶은데 말이죠.

사용한 컴파일러는 gcc 2.95.3-6이고, 안되는 컴파일러는 ADS 1.2입니다.
그리고 union입니다. struct이면 가능한 방법이 몇가지 있던데, union은 안되더군요.

전웅의 이미지

union A{
		struct {
				unsigned int a ; 
				unsigned int b ;
		} Int0;
		struct {
				unsigned int c ;
				unsigned int d ;
		}Int1;
		int e;
};

#define INT0(a,b) { {a,b}}
#define INT1(c,d) { Int1:{c,d}}

union A aa[]= {
		INT0(1,2),
		INT1(3,2)
};


int main()
{
  int i;

  for(i=0; i<2; i++){
		  printf("%d %d %d %d %d\n", aa[i].Int0.a, aa[i].Int0.b, aa[i].Int1.c, aa[i].Int1.d, aa[i].e);
  }

  return 0;
}

1 2 1 2 1
3 2 3 2 3

elanoia wrote:
질문 1 :
여기서 제가 임의적으로 초기화 하지 않은 변수들에 대한 값들(aa[0].Int0.c, d, e, aa[1].Int0.a, b, e )이 의미있는 값들인지 쓰레기 값인지 알고 싶습니다. 즉, 어떠한 규칙에 의해 생성되는 것인지, 마구잡이식의 쓰레기 값인지 말이죠. 여러번 컴파일 해봐도 같은 값이 나옵니다.

규칙이 있습니다.

일단, Int0 과 Int1 의 두 멤버가 항상 동일한 값으로 초기화된다는 사실은
공통 초기열 (common initial sequence) 이라는 규칙이 보장해 줍니다. 즉,
공용체 안의 구조체 멤버가 호환되는 데이터형의 멤버를 앞 부분에 공유하
고 있기 때문에 Int0 의 a, b, 그리고 Int1 의 c, d 는 서로 같은 offset
으로 할당되고, 또 한 구조체의 공통 초기열에 값을 쓰고, 다른 구조체를
통해 읽는 것은 항상 같은 값을 보장해 줍니다.

(IT 백두대간 C 언어, pp.670-672)

구조체 멤버가 아닌 e 가 규칙적인 결과를 보이는 것은 다음 규칙에 기반합
니다.

- 구조체/공용체의 가장 앞에는 padding 이 없습니다.
- 대응하는 unsigned 정수형과 signed 정수형은 (sizeof 의 관점에서) 같은
크기를 갖습니다.
- 대응하는 unsigned 정수형과 signed 정수형에 대해, unsigned 정수형이
표현할 수 있는 값의 범위와 signed 정수형이 표현할 수 있는 양수값의
범위의 교집합에 속하는 양수값들은 같은 표현을 사용합니다 - 즉,
signed 정수형에 양수값을 저장하고 이를 대응하는 unsigned 정수형으로
type punning 해서 읽으면 올바른 값이 보장됩니다.

(IT 백두대간 C 언어, pp.180-184, p.652)

elanoia wrote:
질문 2:
#define INT1(c,d) { Int1:{c,d}} 과 같이 Int1에 접근을 했는데 다른 방법으로로 접근이 가능하거나, 생성시 초기화가 가능한지요? gcc가 아닌 다른 다른 컴파일러에서는 이런 신택스가 안 통해서 고치고 싶은데 말이죠.

사용한 컴파일러는 gcc 2.95.3-6이고, 안되는 컴파일러는 ADS 1.2입니다.
그리고 union입니다. struct이면 가능한 방법이 몇가지 있던데, union은 안되더군요.

일단 해당 컴파일러의 document 를 살펴보는 것이 우선이겠지만, 만약 C99
를 부분적으로 지원한다면, 다음과 같이 designated initializer 를 사용하
는 방법이 가능합니다.

#define INT1(c,d) { .Int1 = {c,d}}

gcc 역시 C99 를 완벽하게 지원하지는 않아도 이는 지원해주고 있으니 보다
근거있는 방법으로 바꾸시기를 추천합니다.

만약, ADS 1.2 에서 이 방법이 안 되고 특별히 확장으로 지원해 주는 방법
이 없다면 언어 정의상으로는 제공되는 방법이 없습니다 - 초기화가 아닌
직접 해당 멤버에 값을 대입해 사용하거나 다른 꽁수를 쓰는 수 밖에요...

하지만, 위에서 말씀드렸듯이 공통 초기열이 보장되는 경우에는 충분히 활
용하시기 바랍니다.

(IT 백두대간 C 언어, p.672, p.703)

그럼...

--
Jun, Woong (woong at gmail.com)
http://www.woong.org

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.