見出し画像

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

先生の仰っておられることが、だんだんと難しくなってきました。
でも、それが少し分かるととても嬉しい。
日本語の説明は、最初は正直よく理解できないけど、サンプルコードを見ると成る程と分かってくる。

今回の課題は、サンプルコードを修正するだけ、、、の筈なのに、いろんなトラップがある。成る程、簡単には許してくれないってことですね?

課題

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

https://note.com/kazushinakamura/n/n331805b0abe2?magazine_key=m07bb4da8df3e


答案作成上のポイント整理

  • 解説記事に記載された、2バイトのshort integerを16進数表記するコードを修正して利用する。

  • 修正点は、4バイトのintegerを扱えるようにすること

  • 負の数でも正しく表記するために、(unsigned char)にcastする必要があること

  • 16進表記する部分を、関数としてmainから分離すること

  • 「先頭バイトから1バイトづつ」とあるが、私の環境ではリトルエンディアン表記となること

答案(値渡しバージョン)

#include <stdio.h>

union longint {
  int i;
  char b[4];
};
 
void show_hex(union longint v2){
    printf("%011d %02x:%02x:%02x:%02x\n", 
      v2.i,
      (unsigned char) v2.b[0], 
      (unsigned char) v2.b[1], 
      (unsigned char) v2.b[2], 
      (unsigned char) v2.b[3]);
}

void main() {
  union longint v;
  int samples[] = {1, 255, 65535, 16777215, 2147483647, 
    -1, -256, -65536, -16777216, -2147483648, 0};

  for (int i = 0; samples[i] !=0; i++) {
    v.i = samples[i];  
    show_hex(v);
  }

}

こちらは比較的すんなりと出来た。


答案(参照渡しバージョン)

include <stdio.h>

union longint {
  int *i;
  char *b;
};
 
void show_hex(union longint v2){
    printf("%011d %02x:%02x:%02x:%02x\n", 
      *v2.i, 
      (unsigned char) v2.b[0],
      (unsigned char) v2.b[1], 
      (unsigned char) v2.b[2], 
      (unsigned char) v2.b[3]);
}

void main() {
  union longint v;
  int samples[] = {1, 255, 65535, 16777215, 2147483647, 
    -1, -256, -65536, -16777216, -2147483648, 0};

  for (int i = 0; samples[i] !=0; i++) {
    v.i = &samples[i];  
    show_hex(v);
  }

}

当初、構造体のように共用体の名前をポイントして渡すのかと思っていたのでちっともうまくいかない。先生のサンプルコードをよく見直してようやく気づいた。「共用体のメンバーをポイント変数にしないといけないんだ!」


実行結果

00000000001 01:00:00:00
00000000255 ff:00:00:00
00000065535 ff:ff:00:00
00016777215 ff:ff:ff:00
02147483647 ff:ff:ff:7f
-0000000001 ff:ff:ff:ff
-0000000256 00:ff:ff:ff
-0000065536 00:00:ff:ff
-0016777216 00:00:00:ff
-2147483648 00:00:00:80

いかがでしょうか?


後記

そういえば最近、私の姉弟子のAyumiさんがたいへんお忙しいご様子で、答案提出が私だけになってしまっています。私の拙いコードに対する鋭いツッコミが聞けないのがとても残念。無理は言いませんが、早く戻ってきてください!待ってます。


解答(2023.3.10)

蛇足 - 10進数を3桁毎にカンマ編集したバージョン

このコードは、ブラウザ環境版です。
kznさんのアドバイスに従って、共用体のメンバーをunsigned charとしました。やっぱり、10進数は3桁毎にコンマがある方が見易いです。---> lesson17.c(削除済み)

※ clangコンパイラの警告に極力対応しました。(2023.03.30) ---> lesson17_r1.c

              1 01:00:00:00
            255 ff:00:00:00
         65,535 ff:ff:00:00
     16,777,215 ff:ff:ff:00
  2,147,483,647 ff:ff:ff:7f
             -1 ff:ff:ff:ff
           -256 00:ff:ff:ff
        -65,536 00:00:ff:ff
    -16,777,216 00:00:00:ff
 -2,147,483,648 00:00:00:80


ここまで読んでいただき、有難うございます。



いいなと思ったら応援しよう!

Akio van der Meer
これまでの収益は全て、それを必要としておられる方々へ、支援機関を通して寄付させていただきました。この活動は今後も継続したいと思っています。引き続きよろしくお願いいたします。