22

__func__C (C99 / C11) および C++ で定義済みの変数を関数の外で使用するとどうなりますか?

#include <stdio.h>

const char* str = __func__;

int main(void)
{
   printf("%s", str);
   return 0;
}

-Wall -W -pedanticgcc 4.7.2 は (有効な状態で)警告のみを表示し、何も出力しません。

標準はそれについて明示的に何も言いません:

ISO/IEC 14882:2011

8.4.1 一般 [dcl.fct.def.general]

8関数ローカルの定義済み変数__func__は、形式の定義static const char __func__[] = "function-name"; が提供されたかのように定義されます。ここで、関数名は実装定義の文字列です。そのような変数が、プログラム内の他のオブジェクトのアドレスとは異なるアドレスを持つかどうかは指定されていません。

ISO/IEC 9899:2011

6.4.2.2 事前定義された識別子

1識別子__func__は、各関数定義の左中括弧の直後に宣言があるかのように、翻訳者によって暗黙的に宣言されるものとしますstatic const char __func__[] = "function-name"; 。ここで、関数名は字句的に囲んでいる関数の名前です。

ウブ?エラー?または、他の何か?

4

2 に答える 2

24

標準はそれについて明示的に何も言っていません

これは、未定義の動作を意味します。

C標準から(強調鉱山):

(C99, 4.p2) 「制約の外側に現れる「しなければならない」または「してはならない」要件に違反した場合、動作は定義されていません。定義されていない動作は、この国際規格ではそれ以外の場合、「 「定義されていない行動」または行動の明示的な定義の省略による.これら3つの間に強調点の違いはありません;それらはすべて「定義されていない行動」を説明しています.

于 2013-01-02T14:03:06.710 に答える
7

(以前のコメントから昇格)

__func__は予約された名前空間にあるため、実装は名前空間スコープであらゆる目的に使用できます。つまり、実装は__func__関数外の(誤) 使用__func__を診断する必要はありません。charそれが実装者がやりたいことであるかどうかの名前空間スコープの配列。

定義されていないか、文字列などとして定義されている可能性があり、その実装はまだ準拠しています。

したがって、定義されている場合と定義されていない場合があり、使用できる正しい型である場合とない場合があるため、関数の外で使用しようとするのは未定義の動作です。

問題のコードが適合する実装で使用されたときに未定義の動作をする可能性がある具体的な例については、実装がそれを定義できると信じていますnullptr(そのため、例は でクラッシュしprintfます) または逆参照に展開されるマクロに定義することさえできますヌル ポインターの、次に#undef各関数へのエントリ時、および各関数#defineの後にそれを実行します (そのため、この例は開始前にクラッシュしmainます!)

于 2013-01-02T14:30:17.837 に答える