C言語のアラインメントの_Alignas指定子と_Alignof演算子の使い方を教えて!
こういった悩みにお答えします.
本記事の信頼性
- リアルタイムシステムの研究歴12年.
- 東大教員の時に,英語でOS(Linuxカーネル)の授業.
- 2012年9月~2013年8月にアメリカのノースカロライナ大学チャペルヒル校(UNC)コンピュータサイエンス学部で客員研究員として勤務.C言語でリアルタイムLinuxの研究開発.
- プログラミング歴15年以上,習得している言語: C/C++,Python,Solidity/Vyper,Java,Ruby,Go,Rust,D,HTML/CSS/JS/PHP,MATLAB,Assembler (x64,ARM).
- 東大教員の時に,C++言語で開発した「LLVMコンパイラの拡張」,C言語で開発した独自のリアルタイムOS「Mcube Kernel」をGitHubにオープンソースとして公開.
- 2020年1月~現在はアメリカのノースカロライナ州チャペルヒルにあるGuarantee Happiness LLCのCTOとしてECサイト開発やWeb/SNSマーケティングの業務.2022年6月~現在はアメリカのノースカロライナ州チャペルヒルにあるJapanese Tar Heel, Inc.のCEO兼CTO.
- 最近は自然言語処理AIとイーサリアムに関する有益な情報発信に従事.
- (AI全般を含む)自然言語処理AIの論文の日本語訳や,AIチャットボット(ChatGPT,Auto-GPT,Gemini(旧Bard)など)の記事を50本以上執筆.アメリカのサンフランシスコ(広義のシリコンバレー)の会社でプロンプトエンジニア・マネージャー・Quality Assurance(QA)の業務委託の経験あり.
- (スマートコントラクトのプログラミングを含む)イーサリアムや仮想通貨全般の記事を200本以上執筆.イギリスのロンドンの会社で仮想通貨の英語の記事を日本語に翻訳する業務委託の経験あり.
こういった私から学べます.
C言語を独学で習得することは難しいです.
私にC言語の無料相談をしたいあなたは,公式LINE「ChishiroのC言語」の友だち追加をお願い致します.
私のキャパシティもあり,一定数に達したら終了しますので,今すぐ追加しましょう!
独学が難しいあなたは,元東大教員がおすすめするC言語を学べるオンラインプログラミングスクール5社で自分に合うスクールを見つけましょう.後悔はさせません!
目次
【C言語】アラインメントの_Alignas指定子と_Alignof演算子
C言語のアラインメントの_Alignas指定子と_Alignof演算子はC11規格から追加された機能です.
_Alignas指定子と_Alignof演算子は,それぞれalignasとalignofとしてstdalign.hでマクロ定義されています.
1 2 |
#define alignas _Alignas #define alignof _Alignof |
stdalign.hは/usr/include以下にはなく,/usr/lib/gcc/x86_64-linux-gnu/XX/include/stdalign.hにあります(XXばGCCのバージョン番号).
本記事で紹介するコードではalignas/alignofを利用します.
_Alignas指定子は,コンパイラに対し変数をメモリ上の特定の位置に配置(アライメント)するように要求します.
キャッシュのラインサイズを考慮して設定することで,キャッシュのヒット率が向上します.
_Alignas指定子は変数に利用できますが,構造体に利用できません.
※構造体のメンバ変数には利用できます.
構造体をアラインメントしたい場合は,GCC/Clang拡張の__attribute__((aligned(XX))を利用しましょう(XXはアラインメントのバイト数).
構造体に__attribute__((aligned(XX))を利用した例はsizeof演算子の記事にあります.
_Alignof演算子は,指定した型がメモリ上のどの位置に配置されるか(アライメント)を取得する演算子です.
_Alignof演算子と似ているsizeof演算子は,データ型,変数,ポインタ,構造体,配列等のサイズ(大きさ)をバイト単位で計算する演算子です.
_Alignof演算子とsizeof演算子の違いを理解するために,これらの表示結果を比較します.
_Alignas指定子と_Alignof演算子の使い方
_Alignas指定子と_Alignof演算子の使い方は以下になります.
コードではalignas/alignofを利用しています.
また,比較用にsizeof演算子も利用しています.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
/* * Author: Hiroyuki Chishiro * License: 2-Clause BSD */ #include <stdio.h> #include <stdalign.h> struct data { char c[63]; int i; double d; }; struct data2 { char c[63]; int i; alignas(64) double d; }; struct single { char c; }; struct empty { }; int main(void) { int i; alignas(64) int j; printf("alignof(i) = %zu\n", alignof(i)); printf("sizeof(i) = %zu\n", sizeof(i)); printf("alignof(j) = %zu\n", alignof(j)); printf("sizeof(j) = %zu\n", sizeof(j)); printf("\n"); printf("alignof(char) = %zu\n", alignof(char)); printf("sizeof(char) = %zu\n", sizeof(char)); printf("alignof(int) = %zu\n", alignof(int)); printf("sizeof(int) = %zu\n", sizeof(int)); printf("alignof(double) = %zu\n", alignof(double)); printf("sizeof(double) = %zu\n", sizeof(double)); printf("alignof(long double) = %zu\n", alignof(long double)); printf("sizeof(long double) = %zu\n", sizeof(long double)); printf("alignof(char *) = %zu\n", alignof(char *)); printf("sizeof(char *) = %zu\n", sizeof(char *)); printf("\n"); printf("alignof(struct data) = %zu\n", alignof(struct data)); printf("sizeof(struct data) = %zu\n", sizeof(struct data)); printf("alignof(struct data2) = %zu\n", alignof(struct data2)); printf("sizeof(struct data2) = %zu\n", sizeof(struct data2)); printf("alignof(struct single) = %zu\n", alignof(struct single)); printf("sizeof(struct single) = %zu\n", sizeof(struct single)); printf("alignof(struct empty) = %zu\n", alignof(struct empty)); printf("sizeof(struct empty) = %zu\n", sizeof(struct empty)); return 0; } |
実行結果は以下になります.
- int型の変数iのalignof/sizeofは両方とも4バイトだが,jはalignofは64バイトでsizeofは4バイト
- char/int/double/long double/char *型はalignof/sizeofのバイトは同じ
- 構造体は,struct singleのみalignof/sizeofの結果は同じ,他は結果は異なる
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
$ gcc alignas_and_alignof.c $ a.out alignof(i) = 4 sizeof(i) = 4 alignof(j) = 64 sizeof(j) = 4 alignof(char) = 1 sizeof(char) = 1 alignof(int) = 4 sizeof(int) = 4 alignof(double) = 8 sizeof(double) = 8 alignof(long double) = 16 sizeof(long double) = 16 alignof(char *) = 8 sizeof(char *) = 8 alignof(struct data) = 8 sizeof(struct data) = 80 alignof(struct data2) = 64 sizeof(struct data2) = 192 alignof(struct single) = 1 sizeof(struct single) = 1 alignof(struct empty) = 1 sizeof(struct empty) = 0 |
上記の結果になった理由を考察してみましょう!
まとめ
C言語のアラインメントの_Alignas指定子と_Alignof演算子の使い方を紹介しました.
また,_Alignof演算子とsizeof演算子との表示結果を比較しました.
C言語を独学で習得することは難しいです.
私にC言語の無料相談をしたいあなたは,公式LINE「ChishiroのC言語」の友だち追加をお願い致します.
私のキャパシティもあり,一定数に達したら終了しますので,今すぐ追加しましょう!
独学が難しいあなたは,元東大教員がおすすめするC言語を学べるオンラインプログラミングスクール5社で自分に合うスクールを見つけましょう.後悔はさせません!