k-tokitoh

はじめての構造体とか

2019-04-28

ロベールのC++教室 第 1 部 68 章くらいまでざざっと。

コンパイル時に色々教えてくれるの、割と性にあっているかもしれない。

  • 関数名は関数のアドレスを返す。
int main() {
  printf("%p", main); // => 0x10a23eee0
}
  • 配列変数名は先頭の要素のアドレスを返す。
int array[] = {1, 2, 3, 4, 5};
printf("%p", array); // => 0x7ffeeb482a80
printf("%p", &array[0]); // => 0x7ffeeb482a80
  • アドレス[インデックス]*(アドレス+インデックス)は同じ。
int array[] = {10,20,30,40,50};
printf("%d\n", array[3]); // => 40
printf("%d\n", *(array+3)); // => 40
  • signed は符号付き、unsigned は符号なし

  • 接頭辞 sz: string zero terminated

  • sizeof

    • sizeof 変数名でその変数のバイト数を返す
    • sizeof(型名)でその型のバイト数を返す
    • sizeof arrayでその配列全体のバイト数を返す
      • 「原則的に、式中の配列オブジェクトはその配列の先頭要素へのポインタ値を返すが、配列が sizeof のオペランドである場合は例外である。」
      • 参考:sizeof 演算子について - Qiita
    • sizeof *arrayでその配列の最初の要素のバイト数を返す
    • よって、配列の要素数を求めたければsizeof array / sizeof *arrayとする。
    • size_of 演算子の返却値は sizeof_t という特殊な型であり、printf では unsigned long と同様%luを用いる。
    • 配列の要 ruby なら array.size で済むのにな。
int array[] = {1, 2, 3, 4, 5};
printf("%lu\n", sizeof array); // => 20
printf("%lu\n", sizeof *array); // => 4
printf("%lu\n", sizeof array / sizeof *array); // => 5
  • 値渡し/参照渡し

    • 基本的に関数に引数を渡すときは値渡しになる。
    • しかし配列は変数名の正体がポインタなので、ポインタを渡す(参照渡し)になる。
    • 構造体も原則値渡しになってしまうが、サイズがでかくなりがちな構造体をばんばん値渡ししてメモリ上のそこらじゅうにコピーをつくるのは嫌なので、以下のように参照渡しするのがベター。
struct SStudent {
  char szName[16];
  int nEnglish;
  int nMath;
  int nScience;
};

void Disp(SStudent& student) { // この"&"で参照渡し
  printf("%s\n", student.szName);
  printf("%d\n", student.nMath);
}

int main() {
  SStudent students[] = {
    {"yamada", 67, 49, 84}, // 構造体の初期化子は"{ }"で囲む
    {"tanaka", 90, 65, 69}
  };
  for(int i=0; i<(sizeof students/sizeof *students); i++)
  Disp(students[i]);
}