Skip to content
Takym (たかやま) edited this page Oct 6, 2024 · 4 revisions

Takym > QA > NoAlign

アラインメント無効化

結論

VC++ でも GCC でも #pragma pack(1) に対応している。 アラインメントの無効化にはこれを使うべき。

// 現在のアラインメント設定をバックアップする
#pragma pack(push)

// アラインメントを 1 に設定する(つまり、アラインメントを無効化する)
#pragma pack(1)

// 構造体を定義する
typedef struct _STRUCT_A_
{
    // 任意のフィールド変数
} StructA;

// アラインメント設定をバックアップから復元する
#pragma pack(pop)

検証用ソースコード

// GCC   g++ -m64 -o noalign.elf noalign.cpp; ./noalign.elf
// VC++  cl noalign.cpp & noalign

#define STRUCT_DATA		{ int data1; char data2; long long data3; char data4; }

struct A STRUCT_DATA;

#pragma pack(push)
#pragma pack(1)

struct B STRUCT_DATA;

#pragma pack(pop)

struct C STRUCT_DATA;

#ifdef __GNUC__
#define NOALIGN __attribute__((packed))
#else
#define NOALIGN __declspec(align(1))
#endif

struct         D1 STRUCT_DATA NOALIGN;
struct NOALIGN D2 STRUCT_DATA;

struct alignas(1) E STRUCT_DATA;

#include <stdio.h>

int main(int argc, char *argv[], char *envp[])
{
	A  a;
	B  b;
	C  c;
	D1 d1;
	D2 d2;
	E  e;

	printf("A : %4zd (data4: %016llX)\r\n", sizeof(A ), ((long long)(&a .data4 - ((char *)(&a )))));
	printf("B : %4zd (data4: %016llX)\r\n", sizeof(B ), ((long long)(&b .data4 - ((char *)(&b )))));
	printf("C : %4zd (data4: %016llX)\r\n", sizeof(C ), ((long long)(&c .data4 - ((char *)(&c )))));
	printf("D1: %4zd (data4: %016llX)\r\n", sizeof(D1), ((long long)(&d1.data4 - ((char *)(&d1)))));
	printf("D2: %4zd (data4: %016llX)\r\n", sizeof(D2), ((long long)(&d2.data4 - ((char *)(&d2)))));
	printf("E : %4zd (data4: %016llX)\r\n", sizeof(E ), ((long long)(&e .data4 - ((char *)(&e )))));

	return 0;
}

それぞれの指定方法で異なる動作になったり、環境によって機能しなかったりする場合がある。 筆者の環境では #pragma pack(1) を指定した struct B で想定通りに機能した。

編集後記

GCC を使う時は、個人的には、__attribute__((packed)) を多用していたが今後は控える事にする。

Clone this wiki locally