見出し画像

C言語教室 第17回 - 共用体とは何か(回答提出)

こちらの記事の課題に対する回答です。

課題

int 型が4バイトであるとして、1バイトずつアクセスできる共用体を宣言して、整数の値を先頭バイトから1バイトずつ16進数で出力する関数を書きなさい。

例によって箇条書きにする。

  • int 型が4バイトであるとする。

  • 1バイトずつアクセスできる共用体を宣言する。

  • 整数の値を先頭バイトから1バイトずつ16進数で出力する関数を書きなさい。

さあ。
始めましょう。


プログラム

#include <stdio.h>
#include <limits.h>

union uniAnyType
{
	int i;
	char c[sizeof(int)];
};

// ・int 型が4バイトであるとする。
// ・1バイトずつアクセスできる共用体を宣言する。
// ・整数の値を先頭バイトから1バイトずつ16進数で出力する関数を書きなさい。

void dumpData(union uniAnyType data)
{
	int i;
	printf("data (%d) = ", data.i);
	for (i = 0; i < sizeof(data.c); ++i)
	{
		printf("%02x ", (unsigned char)data.c[i]);
	}
	printf("\n");
}

int main()
{
	union uniAnyType data = {0};
	dumpData(data);

	data.i = 1;
	dumpData(data);

	data.i = -1;
	dumpData(data);

	data.i = INT_MIN;
	dumpData(data);

	data.i = INT_MAX;
	dumpData(data);

	return 0;
}

実行結果

data (0) = 00 00 00 00 
data (1) = 01 00 00 00 
data (-1) = ff ff ff ff 
data (-2147483648) = 00 00 00 80 
data (2147483647) = ff ff ff 7f 

コメント

エンディアン

そうか。
ARM はリトルエンディアンなのか。
リトルエンディアンはIntelの専売特許かと思っていたんだけど違うのかしらん。
リトルエンディアンは外部装置が絡むと途端にややこしくなるのであまり好きではない。地道に付き合ってきたものだ。

union 初心者

さて、union であるが。
実は・・・使ったことがない。
30年間使わなかったのだった。
構造体のポインタにキャストしまくってきた。
ちょっと慣れないと右往左往するものです。

シンボル

「union」のシンボルに、はたと悩む。
目的があればいいけれど、特にないので。
「どんな型でもアクセスできる」という意味で「uniAnyType」。

とりあえず次の型だけを含めてみた。

  • int

  • char

ここに「short」を追加するのは易かろうが、「float」や「double」を入れるとどうなるんだか、興味深いかもしれない。
と言いつつも何もしない。

バイト配列のサイズ

『「int」型のサイズは4バイトとしてよい』
というのが課題ではあるが、「int」型のサイズを示すシンボルが何かないかとしばし検索してみる。
だが、ない。
「sizeof」は配列サイズには使えないよなぁ、と思いつつも試しに使ってみる。
すると、なんと、使えた。

うーん。
最近のコンパイラはそうなのか。
私の記憶違いか。
たんに「clang」が頑張っているだけなのか。

初期化子

最初に
 union uniAnyType data = 0;
と書いてコンパイルエラーとなった。

構造体の要素 A と B と C だったら、
 {1, 2, 3}
のように書けばいいけど、
共用体の要素 A か B か C だったら、
どう書けばいいのか。

これは検索すれば簡単にわかって、
『最初の要素に対して初期化子を書く』
ということでいいらしい。

今回の「uniAnyType」の場合は「int i;」を初期化するだけである。
それを {} でくくって書く。

union uniAnyType data = {0};


この記事が気に入ったらサポートをしてみませんか?