Entry

プログラミングメモ - const 外しは原則ご法度の巻

2009年06月08日

Yahoo!知恵袋にはまりつつある自分。少し回答とか書いてたりして。ハンドルは違うけれど,読む人が読むとすぐ分かると思う。

で,こちらの話なんだけれども,回答しようと思ったら締め切られちゃったので,こっちに書いておきます。

c言語勉強中です。

ここにあるソースコード↓
http://newcomer.nuts-choco.com/clang/src/11/11-2.c.txt
にある。
return (char*)str;
はどういう意味なのでしょうか?
わかりません教えてください。

c言語勉強中です。 ここにあるソースコード↓ http://newcomer.nuts-choco.com/clan... - Yahoo!知恵袋

「ここにあるソースコード」というのはこちら。

/*
文字列strの中に、文字cが含まれていれば(複数ある場合は、最も先頭側とする)、
その文字へのポインタを返し、含まれていなければNULLを返す関数
    char *str_chr(const char *str, int c) {}
を作成せよ。
*/

#include    <stdio.h>

char *str_chr(const char *str, int c)
{
    while(*str)	{
        if(*str == c)
            return (char*)str;
        str++;
    }

    return NULL;
}

int main(void)
{
    char str[128];
    int c;
    char *p;

    printf("文字列を入力してください:");
    scanf("%s", str);
    while(getchar() != '\n' );
    printf("検索する文字を入力してください:");
    scanf("%c", &c);

    if( (p = str_chr(str, c)) == NULL )
        printf("指定された文字は見つかりませんでした。\n");
    else
        printf("%cは%d文字目にありました。\n", c, p - &str[0] + 1);
    
    return 0;
}

char *str_chr(const char *str, int c) の return-文で char*型にキャストしてるんですけど,これはダメだろう。わざわざ const でポインタを受けているのに,const を外して返すのは,ポインタの扱いについてポリシーがない証拠です。変更可能な領域なのか,そうでないのか,実装者が決められていないということ。キャストしている理由なんかなくて,ただのつじつま合わせだったりします。

ということで,ベストアンサー。

> 何故いちいちこんなことをしないとコンパイラが反応するのかが

質問者さんは、大きなお世話と思ってるということね。

さあ、なんででしょうね。プログラマの不注意による不具合の作りこみを防止するためなんでしょうか。。。

(snip)

コンパイラによっては、サイレンとモードみたいなオプションがあるかもしれませんから、警告がうるさければ、お使いのコンパイラのオプションを調べてみれば?

c言語勉強中です。 ここにあるソースコード↓ http://newcomer.nuts-choco.com/clan... - Yahoo!知恵袋

せっかくコンパイラが警告を出してくれてるのに……。

このプログラム,そもそもちゃんと動かないもんで(一致する文字があっても「見つからない」と言われる),にんともかんともなんですけれど,製作者さんの意図を精一杯汲んで書き直すと,こうなるんだと思う(体裁を少し直してます)。

#include <stdio.h>

const char *str_chr(const char *str, int c)
{
    while (*str) {
        if(*str == (char)c)
            return str;
        str++;
    }
    return NULL;
}

int main(void)
{
    char str[128];
    int c;
    const char *p;

    printf("文字列を入力してください:");
    scanf("%s", str);
    while (getchar() != '\n' );
    printf("検索する文字を入力してください:");
    scanf("%c", &c);

    if((p = str_chr(str, c)) == NULL)
        printf("指定された文字は見つかりませんでした。\n");
    else
        printf("%cは%d文字目にありました。\n", c, p - &str[0] + 1);

    return 0;
}

修正したのは次の点。

  • str_chr() 関数の返値を const char* 型に変更
  • main() 関数内のポインタ p の型を const char* 型に変更
  • str_chr() if-文内の条件で,int c を char 型にキャスト

これで動くようになりました。コンパイラの警告も出ません。

const 指定したポインタを使うなら,原則として const 外しはご法度です。これくらいの小さなプログラムならまだいいんですけれど,ライブラリを作るとか,クラスのインターフェイスを作るとかいった話になると,他のモジュールと契約関係が生まれてしまいます。const 指定されたポインタは,内部で変更されることがないことが保証されている,と,ライブラリの利用者は常識的に考えるわけで,中で勝手に const を外されたら,利用者はたまったもんじゃありません。

質問者さんの疑問は,至極まっとうなものだったという話。

Trackback
Trackback URL:
Ads
About
Search This Site
Ads
Categories
Recent Entries
Log Archive
Syndicate This Site
Info.
クリエイティブ・コモンズ・ライセンス
Movable Type 3.36
Valid XHTML 1.1!
Valid CSS!
ブログタイムズ

© 2003-2012 AIAN