共通のデータ・メモリ使用に関する一般的な問題(データ型が占めるメモリ容量、大端小端、構造体結合体)
一般的なデータ型使用メモリサイズ:(コンパイラによって異なります)一般的に
32ビットコンパイラ:
char:1バイトchar*(ポインタ変数):4バイト(32ビットのアドレス空間は2^32、すなわち32ビット、すなわち4バイト.同理64ビットコンパイラ)short int:2バイトint:4バイトunsigned int:4バイトfloat:4バイトdouble:8バイトlong:4バイトlong long:8バイトunsigned long:4バイトunsigned long:4バイト
64ビットコンパイラ:
char:1バイト
char*(ポインタ変数):8バイトshort int:2バイトint:4バイトunsigned int:4バイトfloat:4バイトdouble:8バイトlong:8バイトlong long:8バイトunsigned long:8バイトunsigned long:8バイト
構造体:
構造体の容量計算には位置合わせが必要です.すなわち、各データが格納されるとき、前のバイトオフセット量は、そのデータサイズの整数倍(すなわち、整列)でなければならず、最後に構造体は、そのメンバーの中で最も整列数の大きいメンバーに従って整列しなければならない.
例えば、struct A{int a;0-3 4-7メモリの整列を保証するために充填する原則double b;8-15 char c[9];16-24}まずaにメモリを割り当て、intが4バイトを占め、次にbにメモリを割り当て、doubleが8バイトを占めるため、8バイトで整列し、開始ビットは8(8%8=0)、bは8-15である.最後にcharは1バイトを占めるので、cは16-24です.従って、構造体Aの大きさは8+8+9=25である.25は、構造体の最大占有メモリタイプdoubleタイプサイズ(8)の整数倍ではないため、Aの最後のサイズは32である.struct B{int a; double b; double c; char d; }; 同様に、上記の分析方法によって、各変数のメモリ内の位置を決定する:a,0-3; ,4-7;b,8-15;c,16-23;d,24; TOTAL=25は8の倍数ではないので、最後のBサイズは32です.構造体を計算する手順1.メモリアライメントは、コンパイラの設定に関係しています.まず、コンパイラのデフォルト値がどのくらいなのかを明らかにします.2.コンパイラのデフォルトをしたくない場合は、#pragma pack(n)でnアライメント3.構造体ごとの変数アライメントを指定します.アライメントパラメータn、変数がバイト数(m)、メモリアドレスの開始位置%min(n,m)=0です.すなわち、最小長規則4.構造体の合計サイズ:整列後の長さは、メンバーの最大整列パラメータの整数倍である必要があります.5.補足:構造体Aの中に構造体Bがある場合、Bの位置合わせはその中で最も長いメンバーの位置合わせを選択するので、構造体の大きさを計算するには3歩進み、まず現在のプログラムがいくつかの位置合わせ(1、2点参照)に従っていることを確定し、次に各構造体の変量の大きさとオフセットを計算し(3、5参照)、最後に構造体の総サイズを計算する(4参照).
けつごうたい
連合体union定義:
C Programming Languageという本では、連合体についてこう述べています.
1)連合体は構造である;
2)そのすべてのメンバーのベースアドレスに対するオフセット量は0である.
3)この構造空間は、最も「幅の広い」メンバーを収容するのに十分な大きさである.
4)すべてのメンバーに合わせるように配置されます.
複数のデータが共有メモリを必要とする場合、または複数のデータが毎回一時的にのみ取得される場合、連合体(union)を利用することができる.コンビネーション内のすべてのメンバーはメモリを共有しているため、各メンバーの格納ヘッダアドレスは、コンビネーション変数のベースアドレスに対するオフセット量が0であり、すなわち、すべてのメンバーのヘッダアドレスが同じである.すべてのメンバーがメモリを共有できるようにするには、これらのメンバーの中で最も広いメンバーを収容するのに十分なスペースが必要です.この「整列はすべてのメンバーに適合する」とは、すべてのメンバーの自己整列に適合する必要があることを意味します.(この会話の理解に注意)
sは10バイト、nは4バイト、dは8バイトであるため、少なくとも10バイトの空間が必要である.しかし、実際のサイズは10ではなく、演算子sizeofでテストするサイズは16である.これは,ここでバイト整列の問題があり,10は4でも8でも整列できないためである.したがって、バイトは16に追加され、すべてのメンバーの自己整列に合致します.ここから、連合体が占める空間は、最も広いメンバーに依存するだけでなく、すべてのメンバーと関係があることがわかります.すなわち、その大きさは2つの条件を満たす必要があります.1)最も広いメンバーを収容するのに十分な大きさです.2)サイズは、含まれるすべての基本データ型のサイズによって割り切れる.
union U2 { char s[5]; int n; double d; };
sは5バイト、nは4バイト、dは8バイトであるため、少なくとも8バイトのスペースが必要となる.一方,char型は1バイト,intは4バイト,doubleは8バイト,その最小公倍数は8バイトであるため,U 2すなわち8バイトでよい.
連合体unionとサイズ端子(big-endian、little-endian):
[cpp] view plain copy
#include
union var{
char c[4];
int i;
};
int main(){
union var data;
data.c[0] = 0x04;//charタイプなので、あまり数字を大きくしないでasciiの範囲を計算します~ data.c[1] = 0x03;//16進数と書くメモリの値比較を簡単にするため data.c[2] = 0x02;
data.c[3] = 0x11;
//配列の下付き文字は低く、アドレスも低く、アドレスごとに低くから高く、メモリ内容は04,03,02,11の順である.全部で4バイト!
//そして、4バイトを1つの全体として(タイプを問わず、直接16進数を印刷する)、メモリの高いアドレスから低いアドレスまで見るべきで、0 x 1020200304、低いビット04は低いアドレスに置かれる.
printf("%x",data.i);
}
結果:
11020304
私の32ビットlinuxがリトルエンドであることを証明します(little-endian)
サイズエンドストレージの問題:
小さい端:低いアドレスは低いバイトを保存します--高いアドレスは高いバイトを保存します
大端:低アドレス高バイト-高アドレス低バイト
組み込みシステム開発者は、Little-endianおよびBig-endianモードについてよく知っているはずです.Little-endianモードのCPUによるオペランドの格納方式は低バイトから高バイト、Big-endianモードによるオペランドの格納方式は高バイトから低バイトである.例えば、16 bit幅の数0 x 1234のLittle-endianモードCPUメモリにおける格納方式(アドレス0 x 4000から格納を開始すると仮定)は、
メモリアドレス
0x4000
0x4001
コンテンツの保存
0x34
0x12
Big-endianモードCPUメモリの格納方法は次のとおりです.
メモリアドレス
0x4000
0x4001
コンテンツの保存
0x12
0x34
32 bit幅の数0 x 12345678 Little-endianモードCPUメモリに格納する方法(アドレス0 x 4000から格納を開始すると仮定)は、
メモリアドレス
0x4000
0x4001
0x4002
0x4003
コンテンツの保存
0x78
0x56
0x34
0x12
Big-endianモードCPUメモリの格納方法は次のとおりです.
メモリアドレス
0x4000
0x4001
0x4002
0x4003
コンテンツの保存
0x12
0x34
0x56
0x78
連合体unionの格納順序は、すべてのメンバーが低アドレスから格納されます.
プログラミングテストプロセッサは大端ですか、小端ですか.
問題:C関数を書いてください.もしプロセッサがBig_であれば.endianの場合、0を返します.リトルならendianの場合、1を返します.
回答:
int checkCPU( )
{
{
union w
{
int a;
char b;
} c;
c.a = 1;
return(c.b ==1);
}
}
32ビットコンパイラ:
char:1バイトchar*(ポインタ変数):4バイト(32ビットのアドレス空間は2^32、すなわち32ビット、すなわち4バイト.同理64ビットコンパイラ)short int:2バイトint:4バイトunsigned int:4バイトfloat:4バイトdouble:8バイトlong:4バイトlong long:8バイトunsigned long:4バイトunsigned long:4バイト
64ビットコンパイラ:
char:1バイト
char*(ポインタ変数):8バイトshort int:2バイトint:4バイトunsigned int:4バイトfloat:4バイトdouble:8バイトlong:8バイトlong long:8バイトunsigned long:8バイトunsigned long:8バイト
構造体:
構造体の容量計算には位置合わせが必要です.すなわち、各データが格納されるとき、前のバイトオフセット量は、そのデータサイズの整数倍(すなわち、整列)でなければならず、最後に構造体は、そのメンバーの中で最も整列数の大きいメンバーに従って整列しなければならない.
例えば、struct A{int a;0-3 4-7メモリの整列を保証するために充填する原則double b;8-15 char c[9];16-24}まずaにメモリを割り当て、intが4バイトを占め、次にbにメモリを割り当て、doubleが8バイトを占めるため、8バイトで整列し、開始ビットは8(8%8=0)、bは8-15である.最後にcharは1バイトを占めるので、cは16-24です.従って、構造体Aの大きさは8+8+9=25である.25は、構造体の最大占有メモリタイプdoubleタイプサイズ(8)の整数倍ではないため、Aの最後のサイズは32である.struct B{int a; double b; double c; char d; }; 同様に、上記の分析方法によって、各変数のメモリ内の位置を決定する:a,0-3; ,4-7;b,8-15;c,16-23;d,24; TOTAL=25は8の倍数ではないので、最後のBサイズは32です.構造体を計算する手順1.メモリアライメントは、コンパイラの設定に関係しています.まず、コンパイラのデフォルト値がどのくらいなのかを明らかにします.2.コンパイラのデフォルトをしたくない場合は、#pragma pack(n)でnアライメント3.構造体ごとの変数アライメントを指定します.アライメントパラメータn、変数がバイト数(m)、メモリアドレスの開始位置%min(n,m)=0です.すなわち、最小長規則4.構造体の合計サイズ:整列後の長さは、メンバーの最大整列パラメータの整数倍である必要があります.5.補足:構造体Aの中に構造体Bがある場合、Bの位置合わせはその中で最も長いメンバーの位置合わせを選択するので、構造体の大きさを計算するには3歩進み、まず現在のプログラムがいくつかの位置合わせ(1、2点参照)に従っていることを確定し、次に各構造体の変量の大きさとオフセットを計算し(3、5参照)、最後に構造体の総サイズを計算する(4参照).
けつごうたい
連合体union定義:
C Programming Languageという本では、連合体についてこう述べています.
1)連合体は構造である;
2)そのすべてのメンバーのベースアドレスに対するオフセット量は0である.
3)この構造空間は、最も「幅の広い」メンバーを収容するのに十分な大きさである.
4)すべてのメンバーに合わせるように配置されます.
複数のデータが共有メモリを必要とする場合、または複数のデータが毎回一時的にのみ取得される場合、連合体(union)を利用することができる.コンビネーション内のすべてのメンバーはメモリを共有しているため、各メンバーの格納ヘッダアドレスは、コンビネーション変数のベースアドレスに対するオフセット量が0であり、すなわち、すべてのメンバーのヘッダアドレスが同じである.すべてのメンバーがメモリを共有できるようにするには、これらのメンバーの中で最も広いメンバーを収容するのに十分なスペースが必要です.この「整列はすべてのメンバーに適合する」とは、すべてのメンバーの自己整列に適合する必要があることを意味します.(この会話の理解に注意)
union U1
{
char s[10];
int n;
double d;
};
sは10バイト、nは4バイト、dは8バイトであるため、少なくとも10バイトの空間が必要である.しかし、実際のサイズは10ではなく、演算子sizeofでテストするサイズは16である.これは,ここでバイト整列の問題があり,10は4でも8でも整列できないためである.したがって、バイトは16に追加され、すべてのメンバーの自己整列に合致します.ここから、連合体が占める空間は、最も広いメンバーに依存するだけでなく、すべてのメンバーと関係があることがわかります.すなわち、その大きさは2つの条件を満たす必要があります.1)最も広いメンバーを収容するのに十分な大きさです.2)サイズは、含まれるすべての基本データ型のサイズによって割り切れる.
union U2 { char s[5]; int n; double d; };
sは5バイト、nは4バイト、dは8バイトであるため、少なくとも8バイトのスペースが必要となる.一方,char型は1バイト,intは4バイト,doubleは8バイト,その最小公倍数は8バイトであるため,U 2すなわち8バイトでよい.
連合体unionとサイズ端子(big-endian、little-endian):
[cpp] view plain copy
#include
union var{
char c[4];
int i;
};
int main(){
union var data;
data.c[0] = 0x04;//charタイプなので、あまり数字を大きくしないでasciiの範囲を計算します~ data.c[1] = 0x03;//16進数と書くメモリの値比較を簡単にするため data.c[2] = 0x02;
data.c[3] = 0x11;
//配列の下付き文字は低く、アドレスも低く、アドレスごとに低くから高く、メモリ内容は04,03,02,11の順である.全部で4バイト!
//そして、4バイトを1つの全体として(タイプを問わず、直接16進数を印刷する)、メモリの高いアドレスから低いアドレスまで見るべきで、0 x 1020200304、低いビット04は低いアドレスに置かれる.
printf("%x",data.i);
}
結果:
11020304
私の32ビットlinuxがリトルエンドであることを証明します(little-endian)
サイズエンドストレージの問題:
小さい端:低いアドレスは低いバイトを保存します--高いアドレスは高いバイトを保存します
大端:低アドレス高バイト-高アドレス低バイト
組み込みシステム開発者は、Little-endianおよびBig-endianモードについてよく知っているはずです.Little-endianモードのCPUによるオペランドの格納方式は低バイトから高バイト、Big-endianモードによるオペランドの格納方式は高バイトから低バイトである.例えば、16 bit幅の数0 x 1234のLittle-endianモードCPUメモリにおける格納方式(アドレス0 x 4000から格納を開始すると仮定)は、
メモリアドレス
0x4000
0x4001
コンテンツの保存
0x34
0x12
Big-endianモードCPUメモリの格納方法は次のとおりです.
メモリアドレス
0x4000
0x4001
コンテンツの保存
0x12
0x34
32 bit幅の数0 x 12345678 Little-endianモードCPUメモリに格納する方法(アドレス0 x 4000から格納を開始すると仮定)は、
メモリアドレス
0x4000
0x4001
0x4002
0x4003
コンテンツの保存
0x78
0x56
0x34
0x12
Big-endianモードCPUメモリの格納方法は次のとおりです.
メモリアドレス
0x4000
0x4001
0x4002
0x4003
コンテンツの保存
0x12
0x34
0x56
0x78
連合体unionの格納順序は、すべてのメンバーが低アドレスから格納されます.
プログラミングテストプロセッサは大端ですか、小端ですか.
問題:C関数を書いてください.もしプロセッサがBig_であれば.endianの場合、0を返します.リトルならendianの場合、1を返します.
回答:
int checkCPU( )
{
{
union w
{
int a;
char b;
} c;
c.a = 1;
return(c.b ==1);
}
}