2017-03-07 17 views
0

私のプログラムでは、ポインタs1にs2の文字があるかどうかを判断し、s1のその位置へのポインタを返します。そうでない場合はNULLを返します。 このconstポインタのエラーを理解できない

#include <stdio.h> 

char * strpbrk(const char *, const char *); 

int main(void){ 
const char *s1 = "hello"; 
const char *s2 = "world"; 

printf("Repeated character in s1 is %p", *strpbrk(s1, s2)); 

} 

char * strpbrk(const char * s1, const char * s2){ 
char *p1, *p2; 

p1 = s1; 
p2 = s2; 
for(; *p1 != '\0'; p1++){ 
    for(; *p2 != '\0'; p2++){ 
     if(*p1 == *p2){ 
      break; 
     } 
     else{ 
      return '\0'; 
     } 
    } 
} 
return p1; 
} 

はこのエラーを取得してください:

test.c: In function ‘strpbrk’: 
test.c:16:5: warning: assignment discards ‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers] 
    p1 = s1; 
    ^
test.c:17:5: warning: assignment discards ‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers] 
    p2 = s2; 
+5

どちらかこれはエラーではないことを知っておくことが重要ですが、それは警告だ - 全く異なっているそのうちの2つが。そして警告の理由は、 '' const char''ではなく '' char''として 'p1'と' p2'を宣言したからです。 –

+0

警告が表示されますが、エラーは表示されません。 –

+1

私はそのメッセージが明らかだと思います。一方の側にconstポインティーがあり、他方にconst以外のものがあります。あなたは修飾子を捨てます。 – StoryTeller

答えて

0

コンパイラの警告を取り除くための最善の方法は、あなたがp1を返す際にキャストを追加し、その後のconst char型へのポインタにp1p2を変更することです。そうすれば、コードの読者はあなたが文字列の引数を変更するつもりはないことがわかります。

実装には(私がうまくいけば)アイロンをかけたいくつかのバグもありました。

char * strpbrk(const char * s1, const char * s2) { 
    const char *p1, *p2; 

    for (p1 = s1; *p1 != '\0'; p1++) { // out is a label 
     for (p2 = s2; *p2 != '\0'; p2++) { 
      if (*p1 == *p2) { 
       // Match found 
       return (char*)p1; 
      } 
     } 
    } 
    // No match found 
    return NULL; 
} 
+0

'break out;という構文はありません。 – aschepler

+0

@ascheplerそれは私が15年以上Javaをコーディングして得たものです。それを指摘してくれてありがとう。コードが修正されました。 –

+0

私は、キャストが6.7.6.1に従って不十分な振る舞いを引き起こすと信じています。ポインタ型は互換性がありません。修飾子を投げ捨ててはいけません。 – Lundin

0

これはなどstrstrstrpbrk、標準ライブラリ関数のいくつかの矛盾、彼らはconst修飾文字列の中に発見項目に非定数のポインタを返す標準の要求です。これらのライブラリ関数のパラメータにconst-correctnessを追加することを決めたが、戻り値の型には追加しないと標準委員会が喫煙していたものはありません。

標準のCでこのような関数を確実に実装できる方法はありません。これは、 "修飾ポインタからタイプ"への変換が許可されていないためです。 C11 6.7.6.1:

For two pointer types to be compatible, both shall be identically qualified and both shall be pointers to compatible types.

このため、コンパイラの警告が引き続き表示されます。だからあなたの質問への答えは、彼らは意志strpbrkstrstrなどの機能が標準Cで安全かつポータブルに実装され得ることができないということです

Two pointer types that are required to be compatible are not identically qualified, or are not pointers to compatible types (6.7.6.1).

:このルールに違反すること(非規範的)附属書Jで未定義の動作として記載されています非標準言語拡張または別のプログラミング言語のいずれかを使用して実装する必要があります。

標準的な関数宣言を無視し、代わりに有理な関数宣言を使用して解決してください。

char* strpbrk_rw (char* s1, const char* s2); // read/write parameter 

または

const char* strpbrk_ro (const char* s1, const char* s2); // read-only parameter 
関連する問題