sizeof演算子
以下について、sizeofでサイズを調べてみます。
- 文字リテラル
- 空文字
- 文字列リテラル
- char型配列
- int型配列
- int型二次元配列
- int型二次元配列の最上位次元の先頭要素の間接参照
- int型二次元配列の間接参照
- char型配列の集合を管理するポインタ配列
- char型配列の集合を管理するポインタ配列の先頭要素への間接参照
- 構造体
- 構造体ポインタ
- 構造体の間接参照
- 構造体メンバの間接参照
- sizeof演算子の評価結果
1 #include <stdio.h> 2 3 typedef struct NODE{ 4 int id; 5 char name[32]; 6 }NODE; 7 8 int main() 9 { 1 1 #include <stdio.h> 2 3 typedef struct NODE_T{ 4 int id; 5 char name[32]; 6 }NODE_T; 7 8 int main() 9 { 10 char carr[] = "ABCDE"; 11 int iarr[] = {1,2,3,4,5}; 12 int iarr2d[][5] = {{1,2,3,4,5}, {1,2,3,4,5}, {1,2,3,4,5}}; 13 int (*iarr2d_p)[3][5] = &iarr2d; 14 char *carr_parr[] = {"aaa", "bbb", "ccc"}; 15 NODE_T node; 16 NODE_T *pnode; 17 18 /* 文字リテラル */ 19 printf(" 1: sizeof('A') = %2d # 文字リテラル\n", sizeof('A')); 20 /* 空文字 */ 21 printf(" 2: sizeof(\"\") = %2d # 空文字\n", sizeof("")); 22 /* 文字列リテラル */ 23 printf(" 3: sizeof(\"ABCDE\") = %2d # 文字列リテラル\n", sizeof("ABCDE")); 24 /* char型配列 */ 25 printf(" 4: sizeof(carr) = %2d # char型配列\n", sizeof(carr)); 26 /* int型配列 */ 27 printf(" 5: sizeof(iarr) = %2d # int型配列\n", sizeof(iarr)); 28 /* int型二次元配列 */ 29 printf(" 6: sizeof(iarr2d) = %2d # int型二次元配列\n", sizeof(iarr2d)); 30 /* int型二次元配列の最上位次元の先頭要素への間接参照 */ 31 printf(" 7: sizeof(*iarr2d) = %2d # int型二次元配列の最上位次元の先頭要素の間接参照\n", sizeof(*iarr2d)); 32 /* int型二次元配列の間接参照 */ 33 printf(" 8: sizeof(*iarr2d_p) = %2d # int型二次元配列の間接参照\n", sizeof(*iarr2d_p)); 34 /* char型配列の集合を管理するポインタ配列 */ 35 printf(" 9: sizeof(carr_parr) = %2d # char型配列の集合を管理するポインタ配列\n", sizeof(carr_parr)); 36 /* char型配列の集合を管理するポインタ配列の先頭要素への間接参照 */ 37 printf("10: siizeof(*carr_parr) = %2d # char型配列の集合を管理するポインタ配列の先頭要素への間接参照\n",sizeof(*carr_parr)); 38 /* 構造体 */ 39 printf("11: sizeof(node) = %2d # 構造体\n", sizeof(node)); 40 /* 構造体へのポインタ */ 41 printf("12: sizeof(pnode) = %2d # 構造体ポインタ\n", sizeof(pnode)); 42 /* 構造体への間接参照 */ 43 printf("13: sizeof(*pnode) = %2d # 構造体の間接参照\n", sizeof(*pnode)); 44 /* 構造体メンバへの間接参照 */ 45 printf("14: sizeof(pnode->name) = %2d # 構造体メンバの間接参照\n", sizeof(pnode->name)); 46 /* sizeof演算子の評価値 */ 47 printf("15: sizeof(sizeof(char)) = %2d # sizeof演算子の評価結果\n", sizeof(sizeof(char))); 48 49 if(sizeof(char) - 100 < 0) 50 printf("OK\n"); 51 else 52 printf("NG\n"); 53 54 return 0; 55 }
結果は、
1: sizeof('A') = 4 # 文字リテラル 2: sizeof("") = 1 # 空文字 3: sizeof("ABCDE") = 6 # 文字列リテラル 4: sizeof(carr) = 6 # char型配列 5: sizeof(iarr) = 20 # int型配列 6: sizeof(iarr2d) = 60 # int型二次元配列 7: sizeof(*iarr2d) = 20 # int型二次元配列の最上位次元の先頭要素の間接参照 8: sizeof(*iarr2d_p) = 60 # int型二次元配列の間接参照 9: sizeof(carr_parr) = 12 # char型配列の集合を管理するポインタ配列 10: siizeof(*carr_parr) = 4 # char型配列の集合を管理するポインタ配列の先頭要素への間接参照 11: sizeof(node) = 36 # 構造体 12: sizeof(pnode) = 4 # 構造体ポインタ 13: sizeof(*pnode) = 36 # 構造体の間接参照 14: sizeof(pnode->name) = 32 # 構造体メンバの間接参照 15: sizeof(sizeof(char)) = 4 # sizeof演算子の評価結果 NG
- 文字リテラルは、int型なので4バイト。
- 文字列リテラルは、末尾にナル文字が付加されるので、6バイト。
- 空文字列は1バイト。
- 初期値を持つchar型配列は、末尾にナル文字が付加されるので、6バイト。
- 初期値を持つint型配列は、char型配列と違ってナル文字は付加されないので、5*4=20バイト。
- 3 x 5 x 4 = 60バイト。
- 5 x 4 = 20バイト。
- 3 x 5 x 4 = 60バイト。
- 3 x 4 = 12バイト。
- 一要素はint型なので4バイト。
- 4 + 32 = 36バイト。
- ポインタ値のサイズなので4バイト。
- 4 + 32 = 36バイト。
- nameは32バイト。
- 符号なし整数なので4バイト。
文字リテラルがint型であること、初期値を持つchar型配列は末尾にナル文字が付加される、という点は留意したいです。
また、sizeofそのものの注意点として…
- sizeofが返すsize_t型とは、符号なし広義整数型である。「符号なし」のため、
- size_t型は符号なしなので、演算時の二項変換などに注意する。例えば、17〜20行目において、「sizeof(char)-100」の評価結果は「-99」となりそうだが、-演算子の左オペランドがunsignedだが右オペランドが100(signed int)であるため、右オペランドはunsignedに型変換され、評価結果はunsignedとなる。そのため、条件<0は、つねに成立しない。
- C99以前では、sizeof演算子のオペランドは評価されない。例えば、sizeof(i++)において、iはインクリメントしない。ただしC99では可変長配列が導入されたため、sizeofは定数式ではなくなった。