yohhoyの日記

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

gcc

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

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

swap(T, U)とis_swappable_with<T, U>とvector<bool>

C++17標準ライブラリには「型が異なる変数間での値交換(swap)」可能か否かを判定するメタ関数 std::is_(nothrow_)swappable_with<T, U> が存在する。一般的には値交換操作は同一型変数間(swap(T&, T&))で行われるが、プロキシ型(proxy)のような特殊ケースにおいて</t,>…

default指定でdeletedされるムーブ操作とオーバーロード解決

プログラミング言語C++において、“default指定でdeletedされるムーブコンストラクタ/代入演算子(→id:yohhoy:20130203)”はオーバーロード解決に影響しない。これはCWG DR 1402で修正された挙動。 struct X { const int i = 42; // constデータメンバを含む…

fallthrough属性利用時のちょっとした注意点

C++1z(C++17)で追加される fallthrough属性 の利用に関する注意点について。下記コードの★部ではフォールスルー(fallthrough)明示を意図しているが、C++コンパイラはプログラマの期待通り振舞わない。これは末尾セミコロン(;)を忘れたことで、fallthrough属…

return文と暗黙のムーブと型変換

プログラミング言語C++において、関数からの return 文と暗黙のムーブと型変換の関係についてメモ。*1下記コードfunc_implicit_move関数のように return 文にて型変換(unique_ptr→shared_ptr)を伴う場合、C++11/14言語仕様によって振る舞いが異なる。この…

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):該当機能は存在しない。メモリ領…

可変引数リストと非PODクラス型の関係・改

gcc(g++)5以降では、C言語スタイルの可変引数リスト(...)に非PODクラス型(≒普通のC++クラス型)を渡すことができる。注意:この振る舞いはgcc 5以降という特定の処理系でのみ合法であり*1、またC++の型システムを無視するため、強い理由がない限りは利用し…

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

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

C++ demangler on Web

オンラインでC++名前デマングル結果を確認できるWebサービス。gcc(g++), Microsoft Visual C++(MSVC)に対応。 https://demangler.com/ GCC and MSVC C++ Demangler https://d.fuqu.jp/c++filtjs/ c++filtjs 関連URL Is there an online name demangler for C…

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

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

-Wnoexceptオプション

gcc(g++)では、C++関数への noexcept 指定子付け忘れを警告するオプションが提供される。Clangでは未実装。要約: 評価結果がfalseとなる noexcept 式オペランドのみが警告対象。残念ながら非常に限定的。 地味にペナルティを受ける「ムーブコンストラクタ/…

anachronistic old-style base class initializer

gcc(g++)が出力する不思議なエラーメッセージについて。役に立たない昔話。本記事の内容はStack Overflowで見つけた質問と回答に基づく。下記コードはC++言語仕様には違反(ill-formed)しているが、gcc/-fpermissiveオプションでコンパイル可能。 struct B { …

定数式中でのconstexpr関数はnoexcept指定相当

定数式(constant expression)中で呼び出すconstexpr関数は、noexcept指定がされているかのように振る舞う。ただし未定義constexpr関数の呼び出しや、非定数式コンテキストからのconstepxr関数呼び出しは、同ルールの適用外となる。 constexpr int f() { retu…

関数パラメータ型としてのauto?

gcc(g++) 4.9.0以降/gnu++1zモードでは、関数パラメータ型として auto キーワードを利用できる。これはC++1zに向けて提案されているConcepts Lite拡張の一部。2019-01-09追記:C++2a(C++20)言語仕様に向けて、abbreviated function template 構文を含むP114…

const値型へのユーザ定義変換演算子と引数lvalue/rvalueオーバーロードの落とし穴

C++11以降では、ユーザ定義変換演算子(user-defined conversion operator)の戻り値型では const T よりも T としたほうが良い。関数オーバーロードで引数型 const T& および T&& を受ける関数*1へ渡す際に、同関数呼び出し時のオーバーロード解決失敗による…

Generic Lambda×Variadic Template Parameter×Ellipsis

C++14で導入されるジェネリックラムダ(generic lambda)、可変長引数テンプレート(variadic template parameter)、ellipsis(...)の組み合わせによる文法上の曖昧さについて。gccとClangのバグ。 struct { template<typename...Args> auto operator()(Args&&...) const { } } f1</typename...args>…

参照型の{}初期化

C++11で導入されたUniform Initializationと参照型変数に関するメモ。C++11(N3337)言語仕様の問題としてCWG defect #1288で挙げられ、C++14 Draft N3376にてWording修正が適用された。*1 struct S {}; int main() { S v; S & r{ v }; // ?? } gcc gcc 4.8.2…

乱数生成器のサイズ

C++11標準ライブラリに追加された乱数生成器(RNG; Random Number Generator)のオブジェクトサイズについてメモ。注意:具体的なオブジェクトサイズは実装依存となるため、下表は各オブジェクト間のオーダー比較程度に解釈すること。 RNG gcc/64 gcc/32 Clang…

Cスタイルキャスト利用を警告

gcc(g++)において、古いCスタイルキャストが使われた場合に警告するオプション。 -Wold-style-cast (C++ and Objective-C++ only) Warn if an old-style (C-style) cast to a non-void type is used within a C++ program. The new-style casts ('dynamic_ca…

C++名前マングリングの互換性

gcc

gcc(g++)のC++名前マングリング(name mangling)では、意図的に他コンパイラシステムと異なる規則を採用している。GCCオンラインマニュアルより引用(下線部は強調)。 On many platforms, GCC supports a different ABI for C++ than do other compilers, so…

memcachedへのC++TM適用事例レポート

C++1yに向けて提案されているC++ Transactional Memory(C++TM)拡張に関して、gccでの実験的サポートを用いた既存アプリケーション(memcached*1)書き換えに関するレポート。C++TMドラフト仕様v1.1(→id:yohhoy:20120414)に基づく。 ペーパー:(PDF)Transac…

C/C++ char型の符号有無

プログラミング言語C/C++のchar型が、符号あり/符号なしのいずれかは処理系定義(implementation defined)*1。各コンパイラでの実装についてメモ。まとめ: char型を「符号あり(signed)」と仮定しないこと。(とはいえ、この仮定をおくコードは多い…) 特にA…

__COUNTER__マクロ

C/C++プリプロセッサにおいて、一意な識別子名生成に利用できる__COUNTER__マクロについて。非標準機能だが主要コンパイラで一通りサポートされている。 #define CAT_IMPL(s1, s2) s1##s2 #define CAT(s1, s2) CAT_IMPL(s1, s2) #ifdef __COUNTER__ #define …

copy elision抑止オプション

gcc(g++)において、C++言語仕様で許容されているcopy elision*1を明示的に抑止するオプション。 -fno-elide-constructors The C++ standard allows an implementation to omit creating a temporary that is only used to initialize another object of the …

無名(匿名)名前空間の不思議な定義

プログラミング言語C++における無名名前空間(unnamed namespace)*1の、一見すると不思議な(実は根拠がある)定義に関するメモ。本記事はStack Overflow上での質問と回答内容に基づく。 C++言語仕様での定義 C++03 7.3.1.1/p1では、unnamed namespaceの振る…

typeid演算子と参照型/cv修飾

プログラミング言語C++のtypeid演算子における、参照型およびcv修飾(const, volatile)の扱いについてメモ。typeid演算子オペランドに型名(type-id)を指定する場合、下記ルールが適用されることに注意。 対象が参照型(T&, T&&)の場合、参照先の型Tとして扱…

'main' is usually a function

gcc

gccの一風変わった警告メッセージ。下記コードはfalse(1)相当を実装する。 unsigned main = 3275800627u; // xor %eax, %eax ; 0x33 0xc0 // inc %eax ; 0x40 // ret ; 0xc3 // 0xc340c033 = 3275800627 gcc 4.6.3@x86環境の実行結果*1: $ gcc -Wall input…

可変引数リストと非PODクラス型の関係

プログラミング言語C++において、可変引数リスト(“...”, ellipsis)をとる関数に非PODクラス型を渡した場合の振る舞いについてメモ。 void foo(int, ...); std::string s; foo(1, s); // ?? C++03 可変引数リストに非PODクラス型を渡した場合、未定義動作(und…

古のK&R C in 2012

2012年現在のC言語コンパイラでもK&R Cソースコードを扱えるか試したのでメモ。*1結論:gccとMSVCはK&R Cソースコードでもコンパイル可能。 /* K&R style C */ int printf(); int add(); main(argc, argv) int argc; char** argv; { printf("1+2=%d\n", add(…