yohhoyの日記

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

C

ポインタ型への非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末尾にはNUL…

readdir/readdir_r関数のあれこれ

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

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はsi…

書式指定%lsとwchar_t型

C C++

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

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文字までは言語仕様にて保証。それ以上は環境限界に従う。 509 = 512バイト − CRLF改行(2) − NUL終端(1) C9…

複合リテラルの有効期間

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/(2021-04-09現在サイト消滅) https://github.com/NSHipster/clangwarnings.com

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

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

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

printf関数ファミリの滅多に使われない書式指定%nを利用したコードの例。本記事の内容はStack Overflowで見つけた質問と回答に基づく。2021-10-11追記:C2x(C23)に向け N2834 にて%nの非推奨化(deprecate)が提案されている。 int n; printf("%s: %nFoo\n", "…

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++では…

(抄訳)N4215 memory_order_consumeの利用と実装に向けて[§5-6のみ]

C++ C

元文書:(PDF)N4215 Towards Implementation and Use of memory_order_consume, P.McKenney/T.Riegel/J.Preshingほか, 2014/10/05訳出メモ: 自分自身の理解のために日本語訳を行ったC++メモリモデル/memory_order_consumeに関する提案文書。§5, 6のみ訳出…

条件変数とデッドロック・パズル(解答編)

条件変数(condition variable)同期プリミティブの利用に関して、不適切な単一スレッド通知notify_oneの使用によるデッドロック(dead lock)発生についてメモ。(条件変数 Step-by-Step入門のおまけ記事) 問題: 1生産者スレッド−1消費者スレッドのとき、mt_s…

条件変数とデッドロック・パズル(出題編)

条件変数(condition variable)同期プリミティブの利用に関して、不適切な単一スレッド通知notify_oneの使用によるデッドロック(dead lock)発生についてメモ。(条件変数 Step-by-Step入門のおまけ記事)スレッド間の非同期データ送受信機構mt_slot<T>として*1、</t>…

条件変数 Step-by-Step入門

長いのでこちら→条件変数 Step-by-Step入門 - yohhoyの日記(別館) コード:https://gist.github.com/yohhoy/d305a6c5249c55ed89a3

ビットフィールド幅の上限値

C C++

プログラミング言語C/C++におけるビットフィールド幅上限値の差異についてメモ。C++でも型サイズを超えるビット幅指定は避けるべき。 struct X { int m : 100; // ?? }; C: 指定した型サイズsizeof(int)*CHAR_BITを超えてはならない。 C++: 型サイズを超えた…

記事"AndroidのためのSMP入門"

Android Developers公式にて公開されているマルチスレッドプログラミング入門記事。主にARMアーキテクチャを対象として、ハードウェア・メモリモデルの理論的説明と、Java/C/C++プログラミングでの実践的な留意点に言及している。(題名に反して、Android固…

パスワードとmemset関数

C言語プログラム上で高機密性情報(パスワード文字列など)を消去するケースで、memset関数の単純利用では機密情報がメモリ上に残存してしまい、セキュリティ上の脆弱性につながる可能性がある。 void secure_operation() { // パスワード文字列を取得 char …

volatile変数とOpenMP flush操作の短い関係

C/C++言語 volatile修飾とOpenMP flush操作の関係についてメモ。要約: OpenMP 2.5以前:volatile変数への読込/書込アクセスは、それぞれ暗黙のOpenMP flush操作を伴う。 OpenMP 3.0以降:volatile変数アクセスはOpenMPメモリモデル(≒Memory Consistency)に…

atomicコンストラクトの制限

OpenMP API仕様バージョンと、C/C++言語向けatomicコンストラクトの制限事項についてメモ。 OpenMP 3.0以前 #pragma omp atomic new-line expression-stmt atomic指示文に続く式 expression-stmt では、スカラ型の左辺値(lvalue)式 x に対する更新操作のみが…

環境依存コード切り替えマクロ

C C++

C/C++プリプロセッサを利用した環境依存コードの切り替え。通常の#ifdef〜#endif方式で切り替えるより見た目が綺麗? unsigned int get_tick_msec() { ENV_windows( return GetTickCount(); ) ENV_linux( struct timespec ts; clock_gettime(CLOCK_MONOTONIC…