N.Y.Cityのまちかど

union_memo

C言語のunion(共用体)に関する覚書

学生から共用体について質問を受けたので、回答のために調べたことをメモ。

そもそも変数・配列・構造体・共用体とは

hensu.png

なお、図において変数名には下線を引いてある。 色付き点線で囲われているのは、囲われたエリアに対しても構造体名、もしくは 共用体名がついていることを示す。

変数(型 変数名 として定義)
変数とは、メモリ空間の一部を確保し、そこに便宜的に名前をつけたもの。 (変数の型は、1つの変数名に対してメモリセルをどれだけ確保するのかを示す)
配列( 型 配列名[] として定義)
配列とは、同一種類の変数を複数個まとめて確保したもの。
構造体(struct 構造体名 … として定義)
構造体とは、複数種類の変数を数個寄せ集めて名前をつけ、固まりでメモリ空間に 確保するもの。
共用体(union 共用体名 … として定義)
共用体(union)は、同じメモリ位置に複数種類の型名を割り付け、一つのメモリ番地を 複数の型として利用するもの。

例:unionを使ってshort型変数の前半と後半を入れ替えるプログラム

ソース
#include<stdio.h>

union uTEST{
	unsigned short	sdt;
	unsigned char	cdt[2];		/*char型要素2個の配列はshortと同じ長さ*/
};

int main(){	
	union uTEST test;
	char buf;
	
	test.sdt = 32832;	/*32832=10000000 01000000*/
	
	printf( "sdt=%d\n", test.sdt );	/* short型として*/
	printf( "cdt[1]=%d\n", test.cdt[1] );	/* char型として*/
	printf( "cdt[0]=%d\n\n", test.cdt[0] );	/* char型として*/
	
	/*バイト単位で入れ替え*/
	buf=test.cdt[0];	/*cdt[0]=01000000*/
	test.cdt[0] = test.cdt[1];	/*cdt[1]=10000000*/
	test.cdt[1] = buf;
	
	printf( "sdt=%d\n", test.sdt );	/* short型として*/
	printf( "cdt[1]=%d\n", test.cdt[1] );	/* char型として*/
	printf( "cdt[0]=%d\n", test.cdt[0] );	/* char型として*/

	return 0;
}
実行結果
sdt=32832
cdt[1]=128
cdt[0]=64

sdt=16512
cdt[1]=64
cdt[0]=128
補足

図で表すとこんなイメージ

union.png

なお、この例はIntel系CPUで実行した場合。 CPUによってはメモリに格納される順番が入れ替わる。 (興味のある人は、ビッグエンディアン、リトルエンディアン 等を調べよ)

例:上と同じことを、ポインタを使って行うプログラム

cptにアドレスを代入する時にで型が違うとWarningが出るが実行可能

ソース
#include<stdio.h>
#include <stdlib.h>	/*mallocのため*/


int main(){	
	unsigned short *spt;
	unsigned char *cpt;
	unsigned char buf;
	
	spt = (short*)malloc(sizeof(short));	/*short型のメモリ確保、short型ポインタをsptに*/
	cpt = spt;	/*char型ポインタとしてsptと同じ位置を参照*/
	
	*spt = 32832;	/*32832=10000000 01000000*/
	
	printf( "sdt=%d\n", *spt );	/* short型として*/
	printf( "cdt[1]=%d\n", cpt[1]);	/* char型として*/
	printf( "cdt[0]=%d\n\n", cpt[0] );	/* char型として*/
	
	/*バイト単位で入れ替え*/
	buf=cpt[0];	/*cdt[0]=01000000*/
	cpt[0] = cpt[1];	/*cdt[1]=10000000*/
	cpt[1] = buf;
	
	printf( "sdt=%d\n", *spt );	/* short型として*/
	printf( "cdt[1]=%d\n", cpt[1] );	/* char型として*/
	printf( "cdt[0]=%d\n", cpt[0] );	/* char型として*/
	
	free(spt);	/*メモリ解放*/
	
	return 0;
}
実行結果
sdt=32832
cdt[1]=128
cdt[0]=64

sdt=16512
cdt[1]=64
cdt[0]=128

現在ご覧のページの最終更新日時は2015/03/15 01:12:01です。

Copyright (C) N.Y.City ALL Rights Reserved.

Email: info[at]nycity.main.jp