ポインタについて

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
ざこ

ポインタについて

#1

投稿記事 by ざこ » 16年前

char buf[10]='ABC';
char *p;

p=buf;

とすると
*pのアドレスが指す中身は"A"
*(p+1)のアドレスが指す中身は'B'だと思います。
この場合
*p自体が文字列Aを指してるのか
*p自体はアドレスでそのアドレスが指す中身がAを指しているのか
どちらなのでしょうか?

また
*p=bufというような表現もよく見かけるのですがこれはpはbuf[0]を指すという意味になると
書いてあったのですがp=bufと同じ意味ですか?

ポインタについてしっかり認識しておきたいので教えてください。

御津凪

Re:ポインタについて

#2

投稿記事 by 御津凪 » 16年前

"p" がアドレスを指し、
"*p" で"p"のアドレスを指している中身(文字列A)を指します。

つまり、

> *p自体が文字列Aを指してるのか
> *p自体はアドレスでそのアドレスが指す中身がAを指しているのか

"*p" が示す意味は前者の方です。
("p"は後者です)

> *p=bufというような表現もよく見かけるのですがこれはpはbuf[0]を指すという意味になると
> 書いてあったのですがp=bufと同じ意味ですか?

*p=buf ではコンパイルエラーになります。
"*p"はp[0]と同じですが、buf は buf[0] と同じ意味でなく、 p == buf (ポインタと同じ)です。

char *p=buf であればコンパイルは通ります。
このとき、"char *p"の部分は、"char *"と"p"に分かれて解釈しますので、
処理としては p=buf と同じです。
("char *"が型の名前、ということです。)
ここはよく混乱しやすいところなので、注意してください。

# char* p=buf のように'*'の位置を型の直後に移動すれば、ある程度理解しやすいかも。

non

Re:ポインタについて

#3

投稿記事 by non » 16年前

>char buf[10]='ABC';
は char buf[10]="ABC"; ですね。

>*pのアドレスが指す中身は"A"
ここは 'A'です。細かいようですが・・・
しっかり区別しましょう。

ざこ

Re:ポインタについて

#4

投稿記事 by ざこ » 16年前

やはりまだあやふやなようです。しっかり覚えます。
ありがとうございました。

ムンバ

Re:ポインタについて

#5

投稿記事 by ムンバ » 16年前

こんばんは。お世話になります。
解決されたのに、ぶら下がりさせて頂きます。ごめんなさい。

今、ポインタの勉強をしてまして参考書の練習問題を解いている真っ最中です。
もう本当にポインタの項目飛ばしちゃおう!くらい悩んだのですが
こちらの掲示板で、何かヒントが見つからないかと拝見してたところ
ざこさんのご質問と、お二方のご解説で、少し前進できた様な感じです。ありがとうございます。
私が勘違いしていた部分を搭載させて頂きます。
コメント(// の行)が、私の勘違い部分です。
#include <stdio.h>

int main()
{
	char *syou;
	syou = "abcdefghijklmnopqrstuvwxyz";

	//char syou[26] = "abcdefghijklmnopqrstuvwxyz";

	printf("%c\n", syou[0]);

	return 0;
}
私はこれで、配列syouに26個の要素が入ると勘違いしてたんですね。

char syou[26] = "abcdefghijklmnopqrstuvwxyz";
printf("%c\n", syou[0]);

で、先頭の要素(a)を表示しようとしてたんです。^^;

このスレッドを読ませて頂いて

char *syou;
syou = "abcdefghijklmnopqrstuvwxyz";

としたら、解決できました。
難しいですね。ポインタ。
練習問題、続けられそうです。^^
どうもありがとうございました。(謝

box

Re:ポインタについて

#6

投稿記事 by box » 16年前

> char syou[26] = "abcdefghijklmnopqrstuvwxyz";
> printf("%c\n", syou[0]);
>
> で、先頭の要素(a)を表示しようとしてたんです。^^;

で、結果はどうだったんですか?
できましたよね?正しいコードですから。

Dixq (管理人)

Re:ポインタについて

#7

投稿記事 by Dixq (管理人) » 16年前

う~んと、、意味がよくわからないです・・。
後、文字列を格納する配列は終端記号を含めた要素数用意しないといけません。

それから、

char *syou;
syou = "abcdefghijklmnopqrstuvwxyz";



char syou[26] = "abcdefghijklmnopqrstuvwxyz";

は意味が違います。
試しに、前者のプログラムにおいて、
途中で文字列の最初の文字をaからzに変更してみたりして下さい。
(アドレスではなくデータの中身を変えようとしてみて下さい)

box

Re:ポインタについて

#8

投稿記事 by box » 16年前

こんなコードを動かしてみて、どちらも同じ結果を得ることを体感してください。

#include <stdio.h>

int main(void)
{
	char s[/url] = "abcdefghijklmnopqrstuvwxyz";
	char *p = "abcdefghijklmnopqrstuvwxyz";
	
	printf("%c\n", s[10]);	// k を出力する
	printf("%c\n", p[10]);	// 同じく k を出力する
	return 0;
}

ムンバ

Re:ポインタについて

#9

投稿記事 by ムンバ » 16年前

boxさん、管理人さん、ご指摘ありがとうございます。
すみません。整理させて下さい。^^;

練習問題(私が参考にさせて頂いてる本の練習問題を、そのまま引用させて頂きます。)

 文字列を反転する("abcd"を"dcba"にする)関数を作り
 これを利用してユーザーの入力した文字列を反転して表示するプログラムを作ってください。
 ただし、文字列には2バイト文字は含まないものとします。
/* try01 */

#include <stdio.h>
#include <string.h>

//char irekae(char *str);

int main(void)
{
	char syou[26] = "abcdefghijklmnopqrstuvwxyz";
	char kou [26] = "zyxwvutsrqponmlkjihgfedcba";
	char str [26];	// 26回以上は、やらない。
	int hikaku;

	while(1){
		printf("a~zの1バイト小文字をz~a(a → z・z → aなど)に変換します。\n");
		printf("半角英小文字を1(バイト)文字のみ、入力して下さい。--- ");

		gets(str);

		if (strcmp(str, "") == 0)	// 何も入力しないでEnter押すとプログラム終了
			break;

		//irekae(str);

		hikaku = strcmp(str, syou);

		printf("\n入力された文字 = %s\n", str);		
		printf("strcmpで比較した値(返り値) = %d\n\n", hikaku);
	}

	return 0;
}

//char irekae(char *str)
//{
	//char syou[26] = "abcdefghijklmnopqrstuvwxyz";
	//char kou [26] = "zyxwvutsrqponmlkjihgfedcba";
	//int hikaku;

	//hikaku = strcmp(str, syou);

	//printf("%d\n", hikaku);

	//printf("%s\n", str);
	//printf("%c\n", syou[0]);
	//printf("%c\n", kou[0]);

	//return 0;
//}
↑練習問題を解いている途中でのソースです。
どうにも、うまくいきませんでしたので
このスレッドを参考にさせて頂き、解決しました。ありがとうございました。

スレッドを拝見させて頂いて、私のソースが訳が解らないソースだと気づきました。
もう、めちゃくちゃですよね。このソース。(涙
見にくくてすみませんが、この練習問題の解答の結果を聞きたいのではありません。
(お聞きした結果、そうなるかもしれませんが。^^;)

この/* try01 */のソースを試行錯誤しながら
ソース中を

char syou[26] = "abcdefghijklmnopqrstuvwxyz";
printf("%c\n", syou[0]);

としたところ、うまく実行できなかったのです。<boxさん
うまくお伝えできないかもしれませんが
#include <stdio.h>

int main()
{
	//char *syou;
	//syou = "abcdefghijklmnopqrstuvwxyz";

	char syou[26] = "abcdefghijklmnopqrstuvwxyz";

	printf("%c\n", syou[0]);

	return 0;
}
改めて、このソースを実行してみますと
syou[0]→a
syou[1]→b
と、boxさんのおっしゃる通り、うまく実行できました。
/* try01 */ のプログラム内で、このソースを実行した時に
私のミスで、思う様に実行できなかったのだと思います。
(ミスに気が付いたら、また改めてご報告させて頂きます。)
ご指摘、ありがとうございます。

>う~んと、、意味がよくわからないです・・。
 私も何が聞きたいのか言いたいのか、ごちゃごちゃですみません。(自爆
 「ポインタで、必ず?つまずくっ!」って
 参考書や参考HPにも、よく書かれてます。

少しお時間下さい。
ざこさん、ぶら下がり申し訳ないです。(謝

つうこうにん

Re:ポインタについて

#10

投稿記事 by つうこうにん » 16年前

管理人さんがいっているように
>文字列を格納する配列は終端記号を含めた要素数用意しないといけません

× char s[26] = "abcdefghijklmnopqrstuvwxyz";
○ char s[27] = "abcdefghijklmnopqrstuvwxyz";

です。
要素数を省略して次のように書けば

char s[/url] = "abcdefghijklmnopqrstuvwxyz";

27個ぴったり確保してくれます。

また、配列の文字列と文字列リテラルの違いにも気をつけてください。
配列の文字列は変更できますが,文字列リテラルは変更できません。

// 文字列リテラルを確保した配列へコピー(初期化のときだけ)
// これは配列の文字列なので変更ができる。
char s[/url] = "abcdefghijklmnopqrstuvwxyz";
s[0] = 'A'; s[1] = 'B'; s[2] = 'C';
puts(s); // 変更の確認

// 文字列リテラルの先頭アドレスの代入
// 変更できない文字列を指しているだけ。
char *s = "abcdefghijklmnopqrstuvwxyz";
// 次の文も有効。あたらしい文字列リテラルを指す。
s = "Hello";

配列の文字列を指していた場合はもちろん要素の変更ができます。
char s[/url] = "abcdefghijklmnopqrstuvwxyz";
char *p = s;
p[0] = 'A'; p[1] = 'B'; p[2] = 'C';
// 二つの出力命令は同じ文を出力
puts(s); puts(p);

とはいえ、なかには文字列リテラルを変更できてしまう処理系もあるのですが
動作は未定義になっています。
ちなみに、どのようなタイトルの参考書を使用しているのでしょうか?
ちまたにはよくない書籍が大量に氾濫しているので気になります。

box

Re:ポインタについて

#11

投稿記事 by box » 16年前

> >文字列を格納する配列は終端記号を含めた要素数用意しないといけません
>
> × char s[26] = "abcdefghijklmnopqrstuvwxyz";

これ、必ずしも×とは言えません。
文字列終端の'\0'を前提としないコードであれば、
上記の定義で大丈夫です。

つうこうにん

Re:ポインタについて

#12

投稿記事 by つうこうにん » 16年前

> > >文字列を格納する配列は終端記号を含めた要素数用意しないといけません
> >
> > × char s[26] = "abcdefghijklmnopqrstuvwxyz";

>これ、必ずしも×とは言えません。
>文字列終端の'\0'を前提としないコードであれば、
>上記の定義で大丈夫です。

C言語だと単純な文字配列として初期化されて
C++だとコンパイルできないみたいですね。

ムンバ

Re:ポインタについて

#13

投稿記事 by ムンバ » 16年前

こんばんは。できましたっ!^^
管理人さん・boxさん・通行人さん、ご丁寧なご解説ありがとうございました。(謝
皆さんの、ご解説を参考にさせて頂きながら今できました。
参考書は「猫でもわかるC言語」、あと「C苦」というサイトを参考させて頂いてます。
(今回の練習問題は参考書のものです。)
#include <stdio.h>
#include <string.h>

char irekae(char *str, char *syou, char *kou); // 関数のプロトタイプ宣言

int main(void)
{
	char syou[/url] = "abcdefghijklmnopqrstuvwxyz";
	char kou [/url] = "zyxwvutsrqponmlkjihgfedcba";
	//char str [26];

	while(1){
		char str [5] = {0}; // 配列を初期化

		printf("a~zの1バイト小文字をz~a(a → z・z → aなど)に変換します。\n");
		printf("半角英小文字を1(バイト)文字のみ、入力して下さい。--- ");

		gets(str);
		
		if (strcmp(str, "") == 0)	// 何も入力しないでEnter押すとプログラム終了
			break;

		irekae(str, syou, kou);

		printf("\n入力された文字 = %s\n", str);
		printf("置換された文字 = %c\n\n", *kou);
	}

	return 0;
}

char irekae(char *str, char *syou, char *kou)
{
	int i = 0;

	while(1){
		if (*str == (*syou + i)){
			//printf("一致しました。\n");
			break;
		}
		i++;
	}

	//*syou = *(syou + i);
	*kou = *(kou + i);

	return 0;
}
配列の大きさは、省略型?にしました。^^;

どうも「アドレス」というのを意識しすぎて
ごちゃごちゃになってしまったのだと思います。
これで、構造体の勉強を始められます。w
皆様、ご指導ありがとうございました。
今後とも、宜しくお願い致します。

non

Re:ポインタについて

#14

投稿記事 by non » 16年前

よくわからないのですが、
この問題を考えていたわけではないのですね。

>練習問題(私が参考にさせて頂いてる本の練習問題を、そのまま引用させて頂きます。)

> 文字列を反転する("abcd"を"dcba"にする)関数を作り
> これを利用してユーザーの入力した文字列を反転して表示するプログラムを作ってください。
> ただし、文字列には2バイト文字は含まないものとします。

どんな問題なんでしょう?

ムンバ

Re:ポインタについて

#15

投稿記事 by ムンバ » 16年前

こんばんは。その問題です。

もっ もしかして「文字列を反転して表示するプログラム」の部分ですか。(汗
void rev(char *str)
{
	char c, *p;

	p = str + strlen(str) - 1;

	while (str < p) {
		c = *str;
		*str++ = *p;
		*p-- = c;
	}
	return;
}


[color=#ce0031" size="-1]「猫でもわかる C言語プログラミング」参考書引用[/color]
(↑この1行、編集画面で追加修正させて頂きました。お騒がせしました。<謝)

こんな感じのですか?

non

Re:ポインタについて

#16

投稿記事 by non » 16年前

それなら、わかります。

ムンバ

Re:ポインタについて

#17

投稿記事 by ムンバ » 16年前

nonさん、ご指摘ありがとうございました。
また何か御座いましたら、突っ込んで下さい。
宜しくお願い致します。

ぶら下らせて頂いた上に、ここまでご指導頂きどうもありがとうございました。
ざこさん、本当に申し訳御座いませんでした。

また何かにぶつかったら質問させて頂きます。
その節は、どうぞ宜しくお願い致します。
どうもありがとう御座いました。(謝

閉鎖

“C言語何でも質問掲示板” へ戻る