構造体定義によるメモリ配置への影響
構造体定義によるメモリ配置への影響:
複数バイトで構成されるshort型やlong型の変数は、メモリ上に配置される場合、ルールがある。
ルール:型サイズの倍数のメモリ番地に配置される。 (アライメント(境界調整)と呼ぶ)
構造体定義された構造体メンバは、記述した順番でメモリに配置される。
アライメント・メモリ配置ルール:
short型:2の倍数の番地に配置
long型:4の倍数の番地に配置
パディング:構造体メンバの型の並びによって、メモリに詰め物が発生する時がある。
パディングが発生しない場合:
https://gyazo.com/d50491948242a7e2f3a19ed68c89c234
パディングが発生する場合:
https://gyazo.com/2ec0a5d3741613ba9041688b22b8875e
メモリアライメント:メモリアドレス番地の位置のこと
キャスト:変数などのデータ型を別の型に変換すること
ワードアクセス:
以下を守って実装することがアライメントを守るという意味になる。
CPUビット数単位のアドレスにCPUビット数単位のデータアクセス(ワードアクセス)
CPUビット数半分単位のアドレスにCPUビット数半分単位のデータアクセス(ハーフワードアクセス)
1byte単位のアドレスアラインに1byte単位のデータアクセス(バイトアクセス)
これらが守れていない場合、アライメントに違反するという
守るためにアドレス番地を調整することをアライメントを調整するという.
気を付けるべきこと:
構造体定義の並び
→並びによって、メモリサイズが異なる事によるバグの発生。
→通信データで構造体で定義した場合、データフォーマットに成らない場合が発生する。
ポインタ型へのキャスト
→ポインタと中のバイトが乖離し、例外に飛んでしまう可能性がある。
例:
code:c
typedef struct {
unsigned long a;
unsigned short b;
unsigned short c;
unsigned long d;
} hoge1;
typedef struct {
unsigned long a;
unsigned short b;
} hoge2;
typedef struct {
unsigned long a;
unsigned short b;
unsigned short c;
unsigned short d;
} hoge3;
typedef struct {
unsigned long a;
unsigned short b;
unsigned long d;
unsigned short c;
} hoge4;
int main(){
printf("long:%d\n",sizeof(long));
printf("short:%d\n",sizeof(short));
printf("hoge1_サイズ:%d\n",sizeof(hoge1));
printf("hoge2_サイズ:%d\n",sizeof(hoge2));
printf("hoge3_サイズ:%d\n",sizeof(hoge3));
printf("hoge4_サイズ:%d\n",sizeof(hoge4));
}
long:8byteのメンバ (64bit)
shory:2byteのメンバ
それぞれ2個ずつ持っている。
hoge1とhoge2で、違うのはメンバの並びだけ。
https://gyazo.com/3107a912baca8651948fbc8c41c455bf
https://gyazo.com/5a8e57819f789af18327e45ebccefb4f
出力結果が異なる。
https://gyazo.com/4f4987a085e527ec09e52cc9da963147
ポインタへのキャストの例:
code:c
int main(int argc, char* argv[])
{
char bytearray[] = { 0,1,2,3 };
long* ptr;
ptr = (long*)bytearray;
pirntf("%x", *ptr);
CPUのメモリについて:
メインメモリ:CPUが直接アクセス出来るメモリで、実行中のプログラムやデータが収められる。
外部メモリ:CPUらは、直接のアクセスはできず、USBやシリアル、パラレルの各種I/Oを通じてアクセスし、現在実行中出ないアプリやデータが収められる。
マイコンのメモリを表すときにROM(読みだし専用メモリ)やRAM(書き換え可能メモリ)が出てくるが、メモリの性質を表した言葉であって、メモリの役割には、関係がない。
アドレス空間:CPUが直接読み書きできる全ての空間。
アドレス空間は、1byteごとに、番号がふられている。
この番号を番地(アドレス)と呼び、一般に16進数で表される。
メインメモリは、全てアドレス空間に含まれます。
サイズに関する情報: