最終更新日 2025年11月18日
warning: padding struct to align ‘i2’
警告:i2′ を整列するため構造体に詰め物した
[-Wpadded]
■この記事の概要
この記事では、C言語でmemcmpを使った構造体の比較に関する問題を解説しています。構造体内のパディング(詰め物)が比較に影響を及ぼし、予期しない動作を引き起こす可能性があります。具体例を挙げ、比較時の注意点や安全な手法について説明しています。
■memcmpの基本的な使い方
#include <stdio.h>
#include <string.h>
int main(void){
char buf1[] = {1,1,1};
char buf2[] = {1,1,1};
char buf3[] = {3,3,3};
int retx = memcmp(buf1,buf2,sizeof(buf1));
puts(retx == 0 ? "同じ" : "違う");
int rety = memcmp(buf1,buf3,sizeof(buf1));
puts(rety == 0 ? "同じ" : "違う");
}
./a.out
同じ
違う■memcmpを文字列比較に使うのは避ける
#include <stdio.h>
#include <string.h>
int main(void){
char s1[32];
char s2[32];
memset(s1,'A',sizeof(s1));
memset(s2,'B',sizeof(s2));
strcpy(s1,"abc");
strcpy(s2,"abc");
int retx = strncmp(s1,s2,sizeof(s1));
puts(retx == 0 ? "同じ":"違う");
int rety = memcmp(s1,s2,sizeof(s1));
puts(rety == 0 ? "同じ":"違う");
}./a.out
同じ
違うs1,s2共に文字列としては”abc”で
同じなのですが、
memcmpは終端文字\0を超えて
指定サイズ分比較するので
strncmpと違う結果になります。
■memcmpの閉じ丸カッコの位置に注意
#include <stdio.h>
#include <string.h>
int main(void){
char *s1 = "abc";
char *s2 = "abc";
size_t size = 3;
puts(strncmp(s1,s2,size == 0) ?"同じ":"違う");
puts(strncmp(s1,s2,size) == 0 ?"同じ":"違う");
puts(memcmp(s1,s2,size == 0) ?"同じ":"違う");
puts(memcmp(s1,s2,size) == 0 ?"同じ":"違う");
}
./a.out
違う
同じ
違う
同じ閉じ丸カッコの位置が間違っているので誤動作します。
■memcmpで構造体の穴にはまる
#include <stdio.h>
#include <string.h>
#include <stdint.h>
typedef struct hole {
uint32_t i1 ;
uint8_t c ;// 3byteの穴
uint32_t i2 ;
} hole ;
static hole g = {1,2,3};
void cmp(void){//メンバの内容が同じ構造体を比較する
hole a = {1,2,3};
int ret = memcmp(&a,&g,sizeof(hole)) ;
puts(ret == 0 ? "同じ" : "違う") ;
}
//自動変数領域全部(穴も)をFFで汚す
void ff(void){
char buf[sizeof(hole)] ;
memset(buf,'F',sizeof(buf));
printf("[%-12.12s]\n",buf);
}
int main(void){
ff(); //自動変数領域をFFで汚す
cmp();
}./a.out
[FFFFFFFFFFFF]
違う構造体のメンバの割り付けはコンパイラ任せなので
各メンバがピッタリ隙間なく割り付けられるとは限りません。
境界調整のために穴が開く場合があり
穴に何が書かれているかは誰もわかりません。
構造体の詰め物(=穴=パディング)の内容は
未規定(=コンパイラ依存)なので、
このプログラムの【穴】に何が入っているのか
わかりません。
参考:
https://www.jpcert.or.jp/sc-rules/c-exp04-c.html
http://www.kouno.jp/home/c_faq/c2.html#8