sizeofに関する問題
3329 ワード
1.sizeofの概念:
sizeofはCの単一演算子であり、そのオペランドの記憶サイズをバイト形式で与える.オペランドは、式または囲まれたデータ型であってもよい.オペランドの格納サイズはオペランドの種類によって決まります.
2.sizeofの使い方:
sizeofは変数にカッコを付けなくてもいいし、カッコを付けてもいいですが、タイプにはカッコを付けなければなりません.sizeofは、関数タイプ、不完全タイプ、ビットフィールドには使用できません.不完全タイプとは、未知サイズの配列タイプ、未知コンテンツの構造または結合、voidタイプなど、位置格納サイズを持つタイプを指します.
3.sizeofとstrlenの比較:
1)sizeofは演算子、strlenは関数
2)sizeofオペレータの結果タイプはsize_t
3)sizeofはタイプでパラメータを作成できますが、strlenはchar*でのみパラメータを作成でき、'0'で終わる必要があります.
4)配列はsizeofのパラメータとして劣化せず,strlenのパラメータとしてポインタに劣化する.(Cの1つの特性:配列をパラメータとして関数に渡す場合、配列はその配列を指すポインタに自動的に劣化します.sizeofは関数ではなく演算子であることに注意してください)
5)ほとんどのコンパイラはコンパイル時にsizeofを計算しているが,これもsizeof(x)を用いて配列サイズを定義できる理由である.
6)strlenの結果は実行時に計算されます.タイプがメモリに占めるサイズを計算するのではなく、文字列の長さを計算するために使用されます.
4.古典的な問題:
5.次のプログラム出力:
構造体のサイズの問題(データの位置合わせ):
デフォルトでは、構造体内の要素のアクセスと管理を容易にするために、構造体内の要素の長さがプロセッサのビット数よりも小さい場合、構造体の中で最も長いデータ要素がその単位であるようにします.つまり、構造体の長さは最も長いデータ要素の整数倍に違いありません.構造内にプロセッサのビット数よりも長い要素がある場合は、プロセッサのビット数を単位とします.しかし、構造体内のタイプが同じ連続要素は、配列と同じ連続空間内にあります.
構造体のデフォルトのバイト位置合わせは、一般的に3つの原則を満たします.
1)構造体変数のヘッダアドレスは、その最も広い基本タイプのメンバー変数の大きさによって除去することができる.
2)構造体の各メンバーの構造体ヘッダアドレスに対するオフセット量は、メンバーサイズの整数倍であり、必要に応じてコンパイラがメンバー間にバイトを追加する.
3)構造体の合計サイズは、構造体の最も広い基本タイプのメンバーサイズの整数倍であり、必要に応じてコンパイラは、最後のメンバーの後にパディングバイトを加算します.
sizeofはCの単一演算子であり、そのオペランドの記憶サイズをバイト形式で与える.オペランドは、式または囲まれたデータ型であってもよい.オペランドの格納サイズはオペランドの種類によって決まります.
2.sizeofの使い方:
sizeofは変数にカッコを付けなくてもいいし、カッコを付けてもいいですが、タイプにはカッコを付けなければなりません.sizeofは、関数タイプ、不完全タイプ、ビットフィールドには使用できません.不完全タイプとは、未知サイズの配列タイプ、未知コンテンツの構造または結合、voidタイプなど、位置格納サイズを持つタイプを指します.
3.sizeofとstrlenの比較:
1)sizeofは演算子、strlenは関数
2)sizeofオペレータの結果タイプはsize_t
3)sizeofはタイプでパラメータを作成できますが、strlenはchar*でのみパラメータを作成でき、'0'で終わる必要があります.
4)配列はsizeofのパラメータとして劣化せず,strlenのパラメータとしてポインタに劣化する.(Cの1つの特性:配列をパラメータとして関数に渡す場合、配列はその配列を指すポインタに自動的に劣化します.sizeofは関数ではなく演算子であることに注意してください)
5)ほとんどのコンパイラはコンパイル時にsizeofを計算しているが,これもsizeof(x)を用いて配列サイズを定義できる理由である.
6)strlenの結果は実行時に計算されます.タイプがメモリに占めるサイズを計算するのではなく、文字列の長さを計算するために使用されます.
4.古典的な問題:
double *(*a)[3][6];
cout<<sizeof(a)<<endl; //4 a
cout<<sizeof(*a)<<endl;//72 *a 3*6
cout<<sizeof(**a)<<endl;//24 **a 6
cout<<sizeof(***a)<<endl;//4 ***a
cout<<sizeof(****a)<<endl;//8 ****a double
5.次のプログラム出力:
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
struct{
short a1;
short a2;
short a3;
}A;
struct{
long a1;
short a2;
}B;
int main()
{
char* ss1 = "0123456789";
char ss2[] = "0123456789";
char ss3[100] = "0123456789";
int ss4[100];
char q1[] = "abc";
char q2[] = "a
";
char* q3 = "a
";
char * str1 = (char*)malloc(100);
void * str2 = (void*)malloc(100);
cout<<sizeof(ss1)<<endl;//4
cout<<sizeof(ss2)<<endl;//11 10 '\0'
cout<<sizeof(ss3)<<endl;//100
cout<<sizeof(ss4)<<endl;//400 , int 4
cout<<sizeof(q1)<<endl;//4 3+1('\0')
cout<<sizeof(q2)<<endl;//3 2+1
cout<<sizeof(q3)<<endl;//4
cout<<sizeof(A)<<endl;//6 2*3
cout<<sizeof(B)<<endl;//8 4+2 8(32 long 4byte)
cout<<sizeof(str1)<<endl;//4
cout<<sizeof(str2)<<endl;//4 。。。。。
return 0;
}
構造体のサイズの問題(データの位置合わせ):
デフォルトでは、構造体内の要素のアクセスと管理を容易にするために、構造体内の要素の長さがプロセッサのビット数よりも小さい場合、構造体の中で最も長いデータ要素がその単位であるようにします.つまり、構造体の長さは最も長いデータ要素の整数倍に違いありません.構造内にプロセッサのビット数よりも長い要素がある場合は、プロセッサのビット数を単位とします.しかし、構造体内のタイプが同じ連続要素は、配列と同じ連続空間内にあります.
構造体のデフォルトのバイト位置合わせは、一般的に3つの原則を満たします.
1)構造体変数のヘッダアドレスは、その最も広い基本タイプのメンバー変数の大きさによって除去することができる.
2)構造体の各メンバーの構造体ヘッダアドレスに対するオフセット量は、メンバーサイズの整数倍であり、必要に応じてコンパイラがメンバー間にバイトを追加する.
3)構造体の合計サイズは、構造体の最も広い基本タイプのメンバーサイズの整数倍であり、必要に応じてコンパイラは、最後のメンバーの後にパディングバイトを加算します.