![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?e8efa67)
#include <stdio.h>
#include <string.h>int main(void)
{
char str[] = "12345""\0""67890";
char* p = strchr(str, '\0');//★strchr関数によりchar* pはポインタpとして扱われ、上と同じような処理になる
//しかしstrchr関数によりchar* pでありながらポインタのアドレス、ではなくアドレスの指す数値を扱うというのに違和感があります。
//これはstrchr関数がそういうものだからと納得するしかないのでしょうか?
printf("|%s|\n", str);
printf("|%s|\n", p + 1);
*p = '!';
printf("|%s|\n", str);
}
をcやc++でデバックしたら、char* p = strchr(str, '\0');の部分がcharと*pになると思ったらchar*とpに分かれていました。
理由がわかりません。
どなたかわかる方はいますでしょうか?
また、char*型とはポインタ型のcharだとわかりました。しかし、だからなんだという感じで、ポインタ型のcharとはなんなのですが?
どうか基礎を固めたいのでどうかよろしくお願い致します。
No.3ベストアンサー
- 回答日時:
str*p
とか
str p
とかって, なんなのさ.
「ポインタ型のchar」も全く意味不明だ. どこにそんなことが書いてあるんだろう.
ちなみに C の文脈で
1byteですよ。数値にすると(符号無しとしたら)0〜255までしか入らん。
と決めつけるのはよくない>#2. char は 1個 1バイトだけどさ.
No.2
- 回答日時:
> str*pにかんしては単純に関数から出る返り値がアドレスであるためなのかなと思っていましたが、だったらchar pでいいじゃんと考えコンパイルすると関数strchrが受け付けないとかでエラーが出ました。
そりゃそうでしょ。
char pで宣言したら変数pは「文字を受け付ける」と言う前提。
前にも書いたけど、静的型付け言語の場合は、左辺と右辺の型が一致してないといけない。
しかも、
> char型 -> 1byte
って書いたでしょ?char型が要求するバイト数っていくら?
1byteですよ。数値にすると(符号無しとしたら)0〜255までしか入らん。16進数だとffです。
ってこたぁ、例えばさっき挙げた例、
0x7ffd753b91f
だと10進数だと何だ、8795410643231か?こんなん入るわけがない。
幼女を強姦するようなモンです。
「らめぇ、大きすぎて無理ぃ」
と言うエロ漫画でお馴染みの展開になる。
そりゃ無理でしょ、と。
No.1
- 回答日時:
> しかしstrchr関数によりchar* pでありながらポインタのアドレス、ではなくアドレスの指す数値を扱うというのに違和感があります。
アドレスの指す数値、って何だろ。アドレスが数値ですよ。メモリの番号。
もう一回言うけど、strchr関数が返すのはアドレスなんです。アドレスをポインタpに代入している。
気になるなら、
printf("%p\n", p);
でも
char* p = strchr(str, '\0');
の後に差し込んで印字してみればいい。
そっちのマシンやコンパイラとは違う数値が印字されるだろうけど、例えばコッチでは
0x7ffd753b91f
と言うのが出てきます。これが「アドレス」。メモリの0x7ffd753b91f番目、って事だな。
だからポインタpにはstrchrから渡ってきたアドレスが入っている。
そして
0x7ffd753b91f
と言う番地には0が格納されてる、ってのがstrchrの機能からの性質です。
何も難しい事はない。
> char* p = strchr(str, '\0');の部分がcharと*pになると思ったらchar*とpに分かれていました。
もう何言ってんだかサッパリ分からんけど、以前書いたの理解してないのかしら。
char *p も char* pも宣言上同じ意味です。256回くらい言いましたが「Cのポインタ周りの文法は腐ってる」。
単に貴方が使ってる環境のデバッガの作者がchar* pって書く方が好きだ、ってだけでしょ。
何にも難しい話じゃない。
> char*型とはポインタ型のcharだとわかりました。しかし、だからなんだという感じで、ポインタ型のcharとはなんなのですが?
うん。だから何だ、ってのは正しい。
アドレスが整数な以上、別に何だって話になるわな、そりゃ。
その感想は正しい。
要するにCにはポインタ演算って言う狂った機能があります。
ポインタpを
p++
として進めたり、p+1したり。
じゃあ、例えばp+1した時、ポインタのアドレスに1足してるのか?って問題がある。
実は違う。
int型もchar型も要求するメモリの容量ってのが違うわけですね。
int型 -> 4byte
char型 -> 1byte
そうすると、「ポインタを一個進めます」って言った場合、型によりその「一個」の量が違う、ってこった。intは4byte進めるけどcharは1byteしか進めない。これが仮に「全く同じ量だけ進める」のならメチャクチャになる。
あるいは、プログラマ側が一個一個手で計算してメモリの塊を跨いでいく、なんつー事をやっても良いんだろうけど・・・考えてみただけでメンド臭い。アセンブリとか機械語出来る人は「そっちの方が明解だ」とか言うかもしれないですけどね(笑)。
だから試しに次のような簡単なコードを書いて確かめてみれば良い。
#include <stdio.h>
int main(void) {
int int_array[] = {1, 2, 3, 4, 5, 6};
char char_array[] = {'H', 'e', 'l', 'l', 'o', '\0'};
int* p, i;
char* q;
p = int_array;
q = char_array;
for (i = 0; i < 6; i++) {
printf("%p ", p);
p += 1;
}
printf("\n");
for (i = 0; i < 6; i++) {
printf("%p ", q);
q += 1;
}
printf("\n");
return 0;
}
// ここまで
intの配列int_arrayとcharの配列char_arrayを用意する。
で、intのポインタpとcharのポインタqの両方を用意する。
pにはint_arrayを代入(正確に言うとint_arrayの先頭のアドレスが代入される)。
そしてqにはchar_arrayを以下同文。
さて、forループでそれぞれのポインタを+1しながらそのアドレスを印字する。
これも実際自分で書いて動かして確認して欲しいんだけど、こっちだとこうなる。
0x7fffa94b5060 0x7fffa94b5064 0x7fffa94b5068 0x7fffa94b506c 0x7fffa94b5070 0x7fffa94b5074
0x7fffa94b505a 0x7fffa94b505b 0x7fffa94b505c 0x7fffa94b505d 0x7fffa94b505e 0x7fffa94b505f
上半分ががpを+1した結果。下がqを+1した結果。上は4づつ増えてるけど下は1づつ増えてるのが分かる?まあ、16進数だから読みづらいんだけど。
このように、ポインタで「型情報」が必要なのは、単純に整数(アドレス値)を代入する、って場合はそれは要らない。けど、ポインタ演算で「1進める」とか「2進める」とかやった場合、「型によって進む"量"が違う」んで、型情報が必要なんですよ。
分かりましたか?
色々ありがとうございます。
str*pにかんしては単純に関数から出る返り値がアドレスであるためなのかなと思っていましたが、だったらchar pでいいじゃんと考えコンパイルすると関数strchrが受け付けないとかでエラーが出ました。
strchrはアドレスを返り値として相手にあげるだけなのにstr pじゃなんでダメなんだろうって感じです。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# 宣言する関数の形が決まっている状態で、 str1とstr2の文字列をこの順に引っ付けてstrに保存し 2 2022/05/30 18:21
- C言語・C++・C# c言語配列の結合についてです。 なぜうまくいかないのでしょうか。 #include <stdio.h 4 2022/05/30 22:42
- C言語・C++・C# c言語 プログラムのエラー 1 2023/02/11 20:31
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
- C言語・C++・C# c言語でユーザ関数を利用して入力された文字列を反転させるプログラムを作りたいです。 3 2023/01/29 19:47
- C言語・C++・C# const char** p;のとき、free(p)でC4090エラーとなるのはなぜですか 3 2023/03/31 16:28
- C言語・C++・C# C言語で再起関数とポインタを用いて文字列反転をする方法がわかりません。 4 2023/04/29 20:32
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- C言語・C++・C# バイナリファイルをコピーするのにかかる時間を測りたいのですが実行するとFatel error:gli 2 2022/11/03 01:10
- C言語・C++・C# Cのdoubleの浮動小数点表示について 3 2023/04/17 13:14
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C言語にて構造体のメンバがNULL...
-
char*を初期化したいのですが
-
CStringからchar*への型変換に...
-
new charとnew char[N]の違いは?
-
SubStringの使い方について
-
カンマで区切った文字の抽出に...
-
文字列の途中から途中までを抽出
-
コマンドライン引数 *argv[]は...
-
'\\0'とはなんですか?
-
C言語の文字リテラル中の16進文...
-
strcpy関数で文字型変数へのポ...
-
関数について
-
char[]をDWORDに格納するには
-
動的メモリの初期化方法について。
-
DWORDとcharの変換
-
csvファイルをfscanfで読み込む...
-
fstream型オブジェクトを関数の...
-
エクセルのMID関数は、C言語では?
-
C言語のintとcharの違いってな...
-
構造体・ビットフィールドのvol...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
char*を初期化したいのですが
-
CStringからchar*への型変換に...
-
C言語のintとcharの違いってな...
-
C言語にて構造体のメンバがNULL...
-
小数点入りの文字列をfloat型に...
-
strcat関数を自作したいです
-
C言語のプログラムについてです
-
const char* s1とただのchar s1...
-
DWORDとcharの変換
-
char型にint型の数値を代入する。
-
文字列の途中から途中までを抽出
-
new charとnew char[N]の違いは?
-
文字列内の数字削除
-
csvファイルをfscanfで読み込む...
-
fgetc( )の戻り値はなぜ整数??
-
char 文字列型 の表現範囲が-12...
-
fstream型オブジェクトを関数の...
-
エクセルのMID関数は、C言語では?
-
ポインタを使って回文かどうか...
-
ポインタ配列
おすすめ情報