C言語関係掲示板

過去ログ

No.451.constポインタの返却

[戻る] [ホームページ]
No.3228

constポインタの返却
投稿者---シスコ(2002/10/30 00:44:06)



こんばんは。シスコです。

また、わからないことができましたので
教えてください。

以下のように、文字列から空白系文字列を
区切りとして、no個目の文字列へのポインタ
を返す関数を作ったのですが、警告がでて
しまいます。
・警告 W8075 db3.c 37: 問題のあるポインタの変換(関数 divspace )

s1の指す内容は特に変更してないので
問題ないとおもいます。


標準関数である
char *strstr(const char *s1, const char *s2)
は、似たようなことができているのですが。


char *divspace(const char *s1, int no)
{
	int flag = 0;
	no--;
	
	/*先頭の空白文字を削除*/
	while(isspace(*s1))
		s1++;
	
	while(*s1 != '\0'){
		if(isspace(*s1)){
			while(isspace(*s1)){
				s1++;
			}
			flag++;
		}
		if(no == flag)
			/*ここが問題の箇所37行目*/
			return(s1);
		s1++;
	}
	return(NULL);
}


No.3230

Re:constポインタの返却
投稿者---kikk(2002/10/30 03:23:38)


ども。


>・警告 W8075 db3.c 37: 問題のあるポインタの変換(関数 divspace )

const char*型とchar*型は双方向には互換性がありません。
以下のコードをコンパイルしてみてください。

const char *cp=NULL; /* 余計な警告を黙らせるためにとりあえずNULL */
char *p=NULL;

p=cp; /* #1 */
cp=p; /* #2 */

#1で同様な警告がでるはずです。

ポインタの代入時には、右辺の型の修飾子を、左辺の型がすべて持って
いなければならないことになっているため、このような警告がでます。
#1では左辺はconstが足りません。#2では右辺の修飾子はなにもないので
問題ありません。左辺と右辺の型が修飾子まで完全に同じでなければ
ならない、***ではない***ので注意してください。なお、この制約は
charに限ったことではありません。


さて、もとのコードですが、

> char *divspace(const char *s1, int no)

という、返り値をchar*型で返すようになっていますが、関数の値の
返却時にも、やはり、代入時と同じような型の制約が要求されます。
なので、型がヘンといわれます。今回はしかたがないので、コンパイラを
黙らせるために、返却時にchar*にキャストしてください。


では。

No.3231

Re:constポインタの返却
投稿者---かずま(2002/10/30 03:35:25)


>・警告 W8075 db3.c 37: 問題のあるポインタの変換(関数 divspace )
>
> s1の指す内容は特に変更してないので
> 問題ないとおもいます。

s1 の型は、const char * 。 divspace の返す型は、char * 。
const char * の値を const char * に代入してはいけないので、警告が出ています。
return (char *)s1; と、明示的にキャストしてやれば、警告は出ません。


> 標準関数である
> char *strstr(const char *s1, const char *s2)
> は、似たようなことができているのですが。

strchr、strrchr、strpbrk についても同様ですが、これらは、引数に const char *
を取り、その文字列中のアドレスを char * で返します。
今の規格が出来る前の C には、const がありませんでしたから、引数も char * で、
何も問題がなかったのです。ところが、新しいい規格に const が導入されてからは、
strstr などのの関数は、引数の文字列を書き換えないということで、その型を
const char * にされてしまったのです。では、関数が返す型も const char * に
すればよいかというと、そうはいきません。char *p; p = strstr(s1, s2);
というように、char * の変数に値を代入するプログラムが多数存在するからです。
そうして、現在のようになったのです。

関数のオーバーロード(名前は同じでも引数が異なれば違う関数)が許される C++ では、
 const char *strstr(const char *s1, const char *s2);
 char *strstr(char *s1, const char *s2);
という 2つの宣言が <cstring> にあります。

No.3250

Re:constポインタの返却
投稿者---シスコ(2002/10/30 22:16:52)


kikkさん。かずまさん。
こんにちは。

レスありがとうございます。

>右辺の型の修飾子を、左辺の型がすべて持って
>いなければならない
まったく知りませんでした。

return文のところでキャストすることで
エラーは出なくなりました。

(char *)型と(const char *)型は、別の型と
考えるべきなのですね。
そのようなキャストができるんですね。

あっと思って参考書を読み直してみたら、
constもlongやshortと同じ装飾子でした。

今回は、質問の内容以上に得るものが
おおきかったです。

本当にありがとうございます!