私は次のテストケースに絞り込んだ奇妙な問題を抱えていました:
inl.h:
inline const char *fn() { return id; }
a.cc:
#include <stdio.h>
static const char *id = "This is A";
#include "inl.h"
void A()
{
printf("In A we get: %s\n", fn());
}
b.cc:
#include <stdio.h>
static const char *id = "This is B";
#include "inl.h"
void B()
{
printf("In B we get: %s\n", fn());
}
extern void A();
int main()
{
A();
B();
return 0;
}
これをコンパイルすると、g++ -O1 a.cc b.cc
正しく動作するようです。私は得る:
In A we get: This is A
In B we get: This is B
しかし、私がコンパイルすると、次のg++ -O0 a.cc b.cc
ようになります。
In A we get: This is A
In B we get: This is A
ここでは実際にC11セマンティクスを使用しようとしていますが、gccはまだC11をサポートしていないため、g++を使用しています。
私が見る限り、C11仕様とC ++仕様(C ++ 11以前の仕様-インライングローバルと静的グローバルのセマンティクスは変更されていないようです)の両方を見ると、私が望むことを実行するはずです、使用時の失敗-O0
はgccのバグです。
これは正しいですか、それとも仕様のどこかに、この未定義の動作を引き起こす何かが欠けていますか?
編集
fn
一般的な答えは、これが機能するために宣言する必要があると主張しているようstatic
です。しかし、C99仕様の6.7.4.6(C11仕様では6.7.4.7-C ++仕様については不明)によると:
変換ユニット内の関数のすべてのファイルスコープ宣言にexternなしのインライン関数指定子が含まれている場合、その変換ユニット内の定義はインライン定義です。インライン定義は、関数の外部定義を提供せず、別の変換単位での外部定義を禁止しません。
したがって、ここには明示的なものがないためextern
、これらは相互作用のない2つの独立したインライン関数である必要があります。明示的なstatic
必要はありません。
明示的な静的を使用すると、Cの問題は修正されますが、C ++インラインメンバー関数では機能しませんstatic
。その場合、キーワードの意味がまったく異なるためです。