2016-10-04 2 views
1

私の質問はこれです。ヘッダ・ファイルにIは、関数宣言がある場合:宣言でのみポインタを制限するよう指定しますか?

extern void func(void* restrict, void* restrict); 

を、次いで、ソース・ファイルに、私はそのように定義する:

void func(void*, void*) {} 

これは問題ですか? restrict修飾子は失われていますか?

P.S.これは、C89モードでソースファイルをコンパイルし、ヘッダーのプロトタイプを条件付きマクロを持つそれぞれのC89/C99バージョンに変更できるためです。

+1

条件マクロがある場合、どちらの定義にも1つの定義を適用しようとしていますか?このようなシナリオに対処する「正しい」方法は、マクロガードによって分割された2つの宣言を提供するか、ガードによって異なる定義が与えられたマクロ識別子の下に問題のあるキーワードを隠すことです。 – Leushenko

答えて

2

「これはので、私はC89モードでソースファイルにコンパイルすることができている」 - シンプルな理由:、restrictはC99 see forword of C11(C99は、第2版です)までは予約語ではないので、それだけで名として使用されますプロトタイプでは無視されます。

しかし、両方の関数宣言子(プロトタイプと定義)は同じ型を指定する必要があります。すなわち、両方ともにrestrictが必要です。

ヘッダーと実装を正しいCバージョンでコンパイルする必要があります。 restrictでは、通常、定義はプロトタイプよりも重要ですが、コンパイラは呼び出し元の違反を検出できる可能性があります。そのようなハッキングに頼ってコードを破壊すると常に仮定します。 clairvoyancyのビットをしようとコメントした後


、:

あなたはコードが古代のC90でコンパイル作る、まだ便利な、マクロを使用することができ、新しい機能を利用したい場合は、次の

#if this_is_c99_or_c11 
#define RESTRICT retrict 
#else 
#define RESTRICT 
#endif 

void f(int * RESTRICT p); 

... 

void f(int * RESTRICT p) 
{ 
    ... 
} 

呼び出し元と呼び出し先をコンパイルする際に問題が発生する可能性があります。ターゲットのABIを確認してください。

+0

名前として使用されますが無視されますが、 'パラメータの再定義'のためにコンパイルに失敗します – DeiDei

+0

どこが失敗するのでしょうか?私の最初の段落の最後の文章をお読みください。 'void *'は定義の宣言子では使用できません。 – Olaf

+0

関数を 'void f(void * restrict、void * restrict);'として宣言すると、C89モードで 'clang-3.9'でコンパイルに失敗し、' error:パラメータ 'restrict'の再定義を引用します。それ以外の場合は、実際に私が何をしているかを答えてくれたので、正しいとマークします。 – DeiDei

関連する問題