2016-05-03 7 views
2

文字列の一部を返す関数を書くときには、戻り値に引数のconst値を使用すると便利です。のconstを定義するには、引数のconst値を使用する機能を持っているように、Cのポータブルな方法があります関数に戻り値として使用される引数 'const'を使用するポータブルな方法はありますか?

extern "C++" 
{ 
extern char *strrchr (char *__s, int __c) 
    __THROW __asm ("strrchr") __attribute_pure__ __nonnull ((1)); 
extern const char *strrchr (const char *__s, int __c) 
    __THROW __asm ("strrchr") __attribute_pure__ __nonnull ((1)); 
.... 

は、例えばC++や__asmを使用して、GNUのlibcにstrstrを取ります戻り値?


注意、もちろんそのことは常に可能代わりに、文字列の回避策として、自己のオフセット戻ります。

+3

まあ、その例はC++です... C++には関数のオーバーロードがあります。 – Lundin

+0

ですが、質問はCについてですが、これを明確にするために編集した質問です。 – ideasman42

+0

@LundinはC11の良い答えですが、C言語の文字列リテラルはconst修飾されていないので、あなたには役に立ちません。 –

答えて

3

邪悪なマクロトリックで可能かもしれません。私もそれを考慮しません。良い解決策は、コンパイル時に使用されるタイプを認識できる_Genericを持つC11が必要です。いくつかのナンセンスコードで

例:

#include <stdio.h> 

#define strrchr(s,c)      \ 
    _Generic((s),       \ 
      char*: strrchr_s,    \ 
      const char*: strrchr_cs) (s,c) 

char *strrchr_s (char *__s, int __c) 
{ 
    printf ("Not constant: %s\n", __s); 
    __s[1] = 'a'; 
    return __s; 
} 

const char *strrchr_cs (const char *__s, int __c) 
{ 
    printf ("Constant: %s\n", __s); 
    return __s; 
} 


int main (void) 
{ 
    char str[] = "Hello"; 

    (void)strrchr(str, 0); 
    (void)strrchr((const char*)str, 0); 

    return 0; 
} 

出力:

Not constant: Hello 
Constant: Hallo 

これはC11のサポートが存在すると仮定すると、100%の標準とポータブルです。

+2

標準テキストはそれに関して曖昧であるため、選択式の配列からポインタへの変換を行わないコンパイラがあります。したがって、 '(s)'の代わりに '&(s)[0]'を持つ方が良いかもしれません。 –

+0

@JensGustedt Hmm。それは良い点です。標準をチェックすると、「一般的なセレクションの制御式は評価されません」と言われます。これは実際には異なる解釈のために開きます。ただし、渡されたパラメータが配列型の場合、デフォルトの関連付けが存在しないため、コードはコンパイルされません。コンパイラエラーを表示させ、呼び出し元が '&str [0]'への呼び出しを再調整させるほうが良いでしょう。 – Lundin

関連する問題