yohhoyの日記

技術的メモをしていきたい日記

C

va_argマクロの奇妙な制限事項

C言語の可変引数リストアクセス用 va_arg マクロにおける奇妙な制限事項についてメモ。va_argマクロの第二引数へ指定する型名には、“関数ポインタ型” や “配列へのポインタ型” を直接記述できない。ただしtypedefによる別名であればOK。こんなコード書くやつ…

nan("is Not-a-Number")

C C++

プログラミング言語C/C++における浮動小数点数 NaN(Not-a-Number)*1 について。C/C++標準ライブラリはquiet NaN*2を返すnan関数を提供し、同関数では処理系定義(implementation-defined)のタグ文字列を受け取る。一般的には空文字列""を指定するが、ライブラ…

CUDA同期メモリ転送関数 != 同期動作

CUDAメモリ転送系関数の Async サフィックス有無*1と、実際の同期(synchronous)/非同期(asynchronous)動作は1:1対応しない。Asyncサフィックス無しメモリ転送関数でも、実際には非同期動作となる可能性がある。 API synchronization behavior The API provi…

Andrew’s C/C++ Token Count Dataset 2016

C++ C

プログラミング言語C/C++のトークン(記号・キーワード・識別子名など)出現頻度を調査したデータセット。約1.1万のOSSパッケージ/256万行のソースコードから5032万個のトークンを抽出。 (PDF) Andrew’s C/C++ Token Count Dataset 2016 (ACTCD16) http://w…

randの既定シード値は1

C

C標準ライブラリ提供の擬似乱数生成関数randでは、既定のシード値は 1 と定義される。 #include <stdlib.h> int main() { // 暗黙にsrand(1)相当でシード値を設定 int x = rand(); } C11 7.22.2.2/p2より引用(下線部は強調)。 The srand function uses the argument </stdlib.h>…

アトミック、ときどきロックフリー

C++ C

C/C++標準ライブラリ提供のアトミック変数 atomic<T>, atomic_T では、ロックフリー(lock-free)性判定マクロ ATOMIC_*_LOCK_FREE*1 が3状態 Never/Sometimes/Always を取りうる。C++11策定当時の提案文書N2427によれば、“ロックリーに振る舞う可能性あり”(AT</t>…

Is volatile useful with threads?

volatileキーワードはマルチスレッド処理に役立つ?.com(http://isvolatileusefulwiththreads.com/) C http://c.isvolatileusefulwiththreads.com/ C++ http://cxx.isvolatileusefulwiththreads.com/ Java http://java.isvolatileusefulwiththreads.com/ C…

配列有効範囲外を指すポインタ値は存在が許されない

C C++

プログラミング言語C/C++における、配列型とポインタ演算の知られざる*1落とし穴。問題:下記sum_odd関数の実行結果は? int data[5] = { 1, 2, 3, 4, 5 }; // 奇数番目の要素値のみを合計する int sum_odd() { int s = 0; int *endp = data + 5; // 配列末…

Designated Initialization @ C++

C++2a(C++20)で導入予定のDesignated Initialization(指示付きの初期化)ついてメモ。C99での同一言語機能をベースとするが、一部機能制限された形でC++に導入される。 // C++2a(C++20) struct Point { int x, y; }; void f(Point); f({ .x = 100, .y = 50 …

初期化子リスト要素数不足時の初期値

C

プログラミング言語Cにおいて、構造体/配列型変数宣言の初期化子リスト(initializer-list)*1で要素数が足りない場合の初期値について。 ポインタ型の場合、ヌルポインタ(NULL) で初期化される。*2 算術型の場合、(正値または符号無し)値0 で初期化される…

ポインタ型への非NULLアノテーションもどき

C99仕様で拡張された構文を用いて、関数引数としてのポインタ型に非NULLアノテーションを行う方法。正直微妙。 int f1(int *p) { if (p == NULL) return 42; return *p; } int f2(int p[static 1]) { if (p == NULL) return 42; return *p; } Clang 3.5/-O1…

Objective-C atomic属性プロパティとスレッド間同期

LLVM/Objective-Cのatomic属性プロパティが保証する性質、C言語(C11)のAtomic変数アクセスとの比較、およびマルチスレッド処理での利用についてメモ。超要約:Objective-C @property宣言には常にnonatomic属性を指定せよ。atomic属性プロパティは人類には早…

数字から数値への変換: ch - '0'

C C++

プログラミング言語C/C++における、1文字の数字から1桁の整数値へ変換するイディオム ch - '0' について。C/C++言語仕様では、数字の文字コード'0'〜'9'がその並び順で連続かつ隣接すると保証する。このため変換元文字chから数字0の文字コード'0'を減算する…

strncpy関数仕様のナゾ

C

C標準ライブラリが提供する strncpy 関数の仕様について。有限長バッファへ文字列を切り詰めてコピーする処理では、strncpy関数が用いられるケースが多い。strncpy関数の仕様として「コピー元srcの文字列長が指定長BUFSIZE以上のとき、コピー先dest末尾にはN…

readdir/readdir_r関数のあれこれ

POSIX環境にて提供されるreaddir、readdir_r関数に関するメモ。まとめ: 事実上スレッドセーフが保証される readdir 関数を使うこと。将来のPOSIX規格でスレッドセーフ保証が追加予定。 readdir_r 関数を利用してはならない。POSIXからも廃止予定であり、GLI…

scanf文字列取得と動的メモリ確保

C標準ライブラリscanf関数の書式指定%sにおいて、取得先の文字列バッファを動的確保する機能拡張。 // POSIX準拠システム char *s = NULL; scanf("%ms", &s); // sはmallocで確保される ... free(s); まとめ: 標準C(ISO C):該当機能は存在しない。メモリ領…

ローカル変数アドレス返却とgccの挙動

警告:C/C++言語においてはローカル変数*1はその変数スコープ内(関数やブロック)でのみ有効であり、同変数へのポインタ値をスコープ外に持ち出すと未定義動作(undefined behavior)を引き起こす。本記事の内容は未定義動作に依存しているため、実行環境のOS…

Linuxとビット幅指定整数型

C99標準ヘッダ<stdint.h>で定義されるビット幅指定の整数型と、Linux Standard Base(LSB)によるプロセッサ・アーキテクチャ別の規定。x86(IA-32)とx86-64/AMD64における整数型ビット幅は下表の通り(太字はアーキテクチャでビット幅が異なる整数型)。 型名 IA-32 AMD6</stdint.h>…

可変引数リストと文字列とヌルポインタの特別な関係

C C++

C言語の可変引数リストと文字列(文字型へのポインタ)とヌルポインタの関係についてメモ。下記コードではvoid*型をもつマクロNULLの値*1を、関数f()実装ではchar*型として展開するが、両ポインタ型は互換型(compatible type)とみなされない*2。関数呼び出し…

size_tと値-1

C C++

C/C++言語における符号無し型と負数の扱いについてメモ。値 -1 をsize_tなどの符号なし整数型*1へ変換代入する場合、同型の最大値となることが保証される。この振る舞いは符号付き整数型の内部ビット表現に依存しない。*2 const size_t nmax = -1; // nmaxは…

書式指定%lsとwchar_t型

C C++

C/C++標準ライブラリ printf/wprintf 関数ファミリでワイド文字列(wchar_t型)を出力する場合、書式指定には常に %ls を利用する。マルチバイト文字列(char型)に対しては、常に %s を利用する。出力先ストリームのバイト指向/ワイド指向(→id:yohhoy:201…

criticalコンストラクトへの名前指定

OpenMPのcriticalコンストラクトには、オプションで名前を指定できる。 int acc = 0; #pragma omp parallel for for (int i = 0; i < 10; i++) { #pragma omp critical (acc) acc += func(i); } OpenMPランタイムによる排他制御では、同じ名前を付与したコー…

文字列リテラル最大長の最低保証

C/C++言語における文字列リテラル(string literal)最大長に対する最低保証について。C言語では文字列長さに関する制約が存在する。*1要約: C90:509文字までは言語仕様にて保証。それ以上は環境限界に従う。 C99以降:4095文字までは言語仕様にて保証。それ…

複合リテラルの有効期間

C

C99で追加された複合リテラル(compound literal)の有効期間についてメモ。 ファイルスコープに記述した場合、静的記憶域期間(static storage duration)を持つ。 ブロックスコープに記述した場合、該当スコープ内でのみ有効となる。 C99 6.5.2.5/p3, 6より引…

C関数ポインタにObjective-Cデリゲートを渡す

関数ポインタ型をとるC言語インタフェースのライブラリに、Objective-C言語のデリゲート(Delegate)を指定する方法。ARC(Automatic Reference Counting)環境を想定。 // XxxLibライブラリ C言語/公開インタフェース // コールバック関数ポインタ型 // nValue:…

Clang警告オプションとメッセージ一覧

LLVM/Clangコンパイラの警告オプション(-Wxxx)と出力メッセージの対応一覧表。Clangソースコードから機械抽出とのこと。 http://fuckingclangwarnings.com/ https://github.com/NSHipster/fuckingclangwarnings.com

OpenMP並列forループの中断処理

OpenMPによる並列forループにおいて、該当ループの処理途中で中断する方法について。OpenMPでは並列forループ内からのbreakは禁止されるため、フラグ変数を用いたループ内処理スキップで代用する。並列リージョンでのフラグ変数アクセスは、全てクリティカル…

printfファミリ書式指定%nの応用例

printf関数ファミリの滅多に使われない書式指定 %n を利用したコードの例。本記事の内容はStack Overflowで見つけた質問と回答に基づく。 int n; printf("%s: %nFoo\n", "hello", &n); printf("%*sBar\n", n, ""); 出力: hello: Foo Bar VisualC++の注意 MS…

sqrt(dx*dx + dy*dy)とhypot(dx, dy)

C C++

C/C++標準ライブラリで2点間距離 (x1,y1) - (x2,y2) を計算する方法。C99以降またはC++11以降では、sqrt関数の他にhypot関数も利用できる。*1 #include <cmath> // C++98 double dist = std::sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)); // C++11以降 do</cmath>…

文字列リテラルは変更できないlvalue

C C++

C/C++言語では、文字列リテラル(string literal)は lvalue に分類される。ただし文字列リテラルの変更は未定義動作(undefined behavior)を引き起こす。文字列リテラル以外のリテラルは rvalue(prvalue) に分類される。(通常の)文字列リテラル型は、C++では…