C sizeof演算子

提供:yonewiki
2022年9月26日 (月) 10:41時点におけるYo-net (トーク | 投稿記録)による版 (ページの作成:「C++へ戻る ※このページではC言語にも存在していたという意味で記事タイトルがC sizeof演算子になっていますが、<br /> C++でも同様です。C++だけの機能がある場合は明記します。<br /> <br /> == '''sizeof演算子''' == 変数が利用しているメモリの大きさを知るための演算子です。演算子ですので、マクロや…」)
(差分) ← 古い版 | 最新版 (差分) | 新しい版 → (差分)

C++へ戻る


※このページではC言語にも存在していたという意味で記事タイトルがC sizeof演算子になっていますが、
C++でも同様です。C++だけの機能がある場合は明記します。

sizeof演算子

変数が利用しているメモリの大きさを知るための演算子です。演算子ですので、マクロや関数として変数の大きさが定義されるようなものではなく、sizeof演算子独自の動作によって、メモリの利用状態を取得しています。sizeof演算子によって返される数字はバイト単位の大きさを整数値で表現するものです。クラスや関数の大きさも取得できるので、かなり大きなサイズになる場合もありますが、せいぜいunsigned int型くらいで表現できる大きさ4GByteに十分収まる大きさだと思います。これ以上の大きさのクラスや関数が存在するとしたら、なんか作り方がおかしいとしかいいようがないですし、別の次元のプログラムになると思われます。そういった技術は独自に演算制御するプログラム言語の世界へと旅立つ必要があるのかなぁと想像します。たぶんそんな状況って無いと思いますけど。


VisualStudioでは、sizeof演算子の戻り値はsize_t型で扱うことになっていますが、結局はunsigned intになることが多いと思います。戻り値は処理系によって異なる型になっていますので、使っている開発環境によっては動きが異なる場合があることは頭の片隅においておく必要があるかもしれません。滅多なことでは、この戻り値の型で悩まされるようなこともないと思います。


演算子ですので、C++だとオーバロード(sizeof演算子を独自の機能として再作成)することもできます。どうやってオーバロードする演算子なのかは、自分も具体的には知りません。sizeof演算子の動作をプログラムによって別の方法で表現する手法がないとうまく再定義はできないはずです。再定義をしたいと思う人はあまりいないと思いますので、オーバロードについてはここでは触れません。時間があったら調べてみようと思います。


sizeof(型名or変数名)


とすることでsizeofのワードに続く括弧の中で指定した型名が利用しているメモリの大きさが4バイトのメモリ空間を利用する形式で返却されます。VisualStudioの場合はunsigned int型の形式と同じものが返って来るようになっています。また変数名で指定した場合はその変数の型名の大きさであったり、変数が静的な配列であれば、配列の大きさを考慮したメモリサイズが返却されます。


sizeof演算子の基本的な使い方を以下に示します。

#pragma once
#include <iostream>

using namespace std;

struct stDate{
  int year;
  int month;
  int day;
};

int _tmain(int argc, _TCHAR* argv[]){
  int pnTestArr[5] = {0,10,20,30,40};
  char pcTestArr[10] = "Size";
  printf("sizeof演算子\n");
  printf("stDate構造体(int型*3個)    = %d[Byte]\n",sizeof(stDate));
  printf("sizeof演算子戻り値のサイズ = %d[Byte]\n",sizeof(sizeof(stDate)));
  printf("\n");
  printf("int型    = %d[Byte]\n",sizeof(int));
  printf("short型  = %d[Byte]\n",sizeof(short));
  printf("char型   = %d[Byte]\n",sizeof(char));
  printf("long型   = %d[Byte]\n",sizeof(long));
  printf("double型 = %d[Byte]\n",sizeof(double));
  printf("float型  = %d[Byte]\n",sizeof(float));
  printf("bool型   = %d[Byte]\n",sizeof(bool));
  printf("size_t型 = %d[Byte]\n",sizeof(size_t));
  printf("\n");
  printf("ポインタ(32bitアプリの場合)     = %d[Byte]\n",sizeof(stDate*));
  printf("int型静的配列  要素5            = %d[Byte]\n",sizeof(pnTestArr));
  printf("char型静的配列 要素10\n");
  printf("pcTestArr           = %d[Byte]\n",sizeof(pcTestArr));
  printf(" (pcTestArr) + 0)   = %d[Byte]\n",sizeof((pcTestArr) + 0));
  printf("*(pcTestArr) + 0)   = %d[Byte]\n",sizeof(*(pcTestArr) + 0));
  printf("pcTestArr[0]        = %d[Byte]\n",sizeof(pcTestArr[0]));
  printf("pcTestArr[5]        = %d[Byte]\n",sizeof(pcTestArr[5]));
  printf("char[10]            = %d[Byte]\n",sizeof(char[10]));
  printf("\n");
}

上記プログラムの出力結果は以下です。

sizeof演算子
stDate構造体(int型*3個)    = 12[Byte]
sizeof演算子戻り値のサイズ = 4[Byte]

int型    = 4[Byte]
short型  = 2[Byte]
char型   = 1[Byte]
long型   = 4[Byte]
double型 = 8[Byte]
float型  = 4[Byte]
bool型   = 1[Byte]
size_t型 = 4[Byte]

ポインタ(32bitアプリの場合)     = 4[Byte]
int型静的配列  要素5            = 20[Byte]
char型静的配列 要素10
pcTestArr           = 10[Byte]
 (pcTestArr) + 0)   = 4[Byte]
*(pcTestArr) + 0)   = 4[Byte]
pcTestArr[0]        = 1[Byte]
pcTestArr[5]        = 1[Byte]
char[10]            = 10[Byte]

上記のように配列の大きさを取得することもできますが、ポインタの型を指定した場合は32ビットアプリならアドレス変数の大きさである4byteが返ってきます。したがって、動的に生成した変数の配列の大きさは取得できません。プログラマ自身が管理する必要のある大きさであることを覚えておくと良いと思います。


まめ知識になるかもしれませんが、1バイトのビット長は処理系によって異なるためCHAR_BITに定義されていることになっています。1Byte = 8bitと決め打ちせずにビット数を求める場合はsizeof(int) * CHAR_BITのように積を求めて値を取得するようにしましょう。sizeof(int) * 8としても、大抵の場合は問題にならないと思いますが、ソースを開示するようなサンプルには汎用性があった方が使いやすいかもしれません。誰が?… コピペする人が。なんじゃそりゃ。どうでもええですね。


C++へ戻る