🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

4回答

2220閲覧

ポインタを使ったプログラムの書き方。

carnage0216

総合スコア194

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2021/02/15 02:03

質問したいことがございます。

まず一つめ

仮に&str[i]のアドレスを上げながらメモリに入った数値をそれぞれの値を+1したい場合は

どう書けばよいのでしょうか?
++str[i++] または str[i++]++
for ( ... ;str[i]++, i++) の方が明快か。
と解答を頂いたのですが、
補足になってしまい申し訳ないですが、
例えば、p は str[i]とも書けるため、ループ三周目のアドレスの指す数値を知りたいときは
if (i == 3){ printf("%d\n", str[3]);};と書けばいいのでしょうか?
仮に
p は str[i]よりよりprintf("%d\n", str[3]);の部分のstr[3]のように書くにはどう書けばいいのでしょうか?if (i == 3){ printf("%d\n", *p ==3);};でしょうか?

二つ目

もう一つ、「仮に&str[i]のアドレスを上げながらメモリに入った数値をそれぞれの値を+1したい場合は
どう書けばよいのでしょうか?
++str[i++] または str[i++]++
for ( ... ;str[i]++, i++) の方が明快か。と言われたのですが、
アドレスとアドレスの指すメモリの数値を上げるならば、++str[i++] または str[i++]++に&を付けてアドレスとアドレスの指すメモリに入る数値を同時にあげる書き方はないのでしょうか?
要は++&str[i++] または &str[i++]++という書き方はないのでしょうか?
ポインタが指すメモリに入った変数の数値と同時に数値を上げるならば
アドレスを上げるのに&の演算子は必要なはずです。
ただ、アドレスを上げながらアドレスの指すメモリに入った数値を上げる書き方が
++str[i++] または str[i++]++と決まっているならば従うしかないですが。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2021/02/15 02:04

まずは、前提とするコードを書いてください。 いきなり「&str[i]」と言われても、型すら定かではありません。
carnage0216

2021/02/15 02:17

すいません、部分的な疑問であったため全体のプログラムはないのです。
maisumakun

2021/02/15 02:21

strの型は何なのですか?
carnage0216

2021/02/15 02:26

strの方はchar型と想定しています。
maisumakun

2021/02/15 02:28

> strの方はchar型と想定しています。 それでは、str[i]自体が文法的に成立しません。
episteme

2021/02/15 02:33 編集

> strの方はchar型と想定しています。 なわけがない。 strがchar型であるなら、 str[i] は意味をなさんから。 あと、唐突に出てきた *p ってなんですか?
carnage0216

2021/02/15 02:40

えと、型を合わせる必要があるのですか? 基礎不足で申し訳ない。 だとしたらstrはint型です。なぜなら変数iがint型だからです。 >>唐突に出てきた *p ってなんですか? ごめんなさい。忘れてください。
episteme

2021/02/15 02:44 編集

> だとしたらstrはint型です。なぜなら変数iがint型だからです。 なわけがない。 strがint型であるなら、 str[i] は意味をなさんから。 int str; str[0] = 1; なんてやらんでしょ?
carnage0216

2021/02/15 02:45

char str[] = "str == NULL ? \"(NULL)\" : str"; のような方ではないのですか? なぜcharはだめなのですか? 混乱してきました。
episteme

2021/02/15 02:52 編集

>> 唐突に出てきた *p ってなんですか? > ごめんなさい。忘れてください。 ならば質問を修正してください。忘れてほしい事項が質問に残っているのは欠陥です。
episteme

2021/02/15 02:51

> char str[] = "str == NULL ? \"(NULL)\" : str"; > のような方ではないのですか? > なぜcharはだめなのですか? strはcharではありません、char配列です。
carnage0216

2021/02/15 02:53

charは配列、、、覚えました。 だとしたらstrは配列型の変数なのですね。
episteme

2021/02/15 03:23

"charは配列" って誰が言いました?
carnage0216

2021/02/15 04:07

私にも問題はあるが、意地悪な人だ。
maisumakun

2021/02/15 04:09

> 私にも問題はあるが、意地悪な人だ。 Cコンパイラも、「融通」など効かせてくれない、ある意味で「意地悪な」存在です。
carnage0216

2021/02/15 04:09

おっしゃる通りです。
episteme

2021/02/15 04:54

> 意地悪な人だ。 「"charは配列" って誰が言いました?」ではなく 「”charは配列" ではありません」って書けばよかった?
carnage0216

2021/02/15 06:09

そろそろ答えを教えてください。
maisumakun

2021/02/15 06:11

> そろそろ答えを教えてください。 すでに多数回答がついている状況で、ことさらに求めるものがあるのであれば、わからない点を強調していただければと思います。
guest

回答4

0

例えばこんな配列があるとしよう.
3つの要素 str[0],str[1],str[2] の値をそれぞれ+1すれば,かわいい動物の名称を示す文字列にすることができる.

C++

1char str[4] = { 'C'-1, 'a'-1, 't'-1 };

そのような処理が行いたいという話なのであれば,最もシンプルな方法はこうだ.

C++

1++str[0]; 2++str[1]; 3++str[2];

やりたいことを素直に実装した.完遂したと言える.

「同じような記述を3回も繰り返すすの嫌だから,俺はループで書くぜ!」とか言うならば,こうだろう.

C++

1for( int i=0; i<3; ++i ) 2{ ++str[i]; }

これで十分ではなかろうか.
これ以上,何を望むのか?

わざわざポインタ型の変数pを持ち出して,以下のようにいろんな形に書くこともできるだろうが,そこには特に面白いこともないように思える.

C++

1char *p = str; 2for( int i=0; i<3; ++i ) 3{ ++( *(p+i) ); }

C++

1char *p = str; 2for( int i=0; i<3; ++i ) 3{ ++p[i]; }

C++

1for( char *p=str; *p; ++p ) 2{ ++(*p); }

結論:難読コードを目指すとかいう話でないならば,素直に書けばどうか.
自分自身で把握し難くなるような文法を持ち出しても無意味な苦労が増えるばかりであろう.


[追記]
以下の2パターンが混じって混乱しているようにも見える.

(1)ポインタpが,常に「いじくるべき要素のアドレス」を指すように pを更新しながら配列要素をいじくる

C++

1//配列の先頭要素のアドレスを指すポインタpがあって… 2char *p = &(str[0]); //単に p = str; でも同じ 3 4//先頭要素の値を100に変更 5*p = 100; 6 7//2番目の要素の値を200に変更する 8++p; //pのアドレスを「2番目の要素のアドレス」に更新して… 9*p = 200; //2番目の要素の値を変更 10 11//3番目の要素の値を300に変更する 12++p; //pのアドレスを「3番目の要素のアドレス」に更新して… 13*p = 300; //3番目の要素の値を変更

(2)ポインタpは「配列の先頭要素のアドレス」を指すもので,いじくる要素のアドレスを「pの値からのアドレスオフセット」で示す

C++

1//配列の先頭要素のアドレスを指すポインタpがあって… 2char *p = &(str[0]); //単に p = str; でも同じ 3 4//先頭要素の値を100に変更 5*p = 100; 6 7//2番目の要素の値を200に変更する 8*(p + 1) = 200; //2番目の要素の値を変更 9 10//3番目の要素の値を300に変更する 11*(p + 2) = 300; //3番目の要素の値を変更

投稿2021/02/15 03:13

編集2021/02/15 05:09
fana

総合スコア11985

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

carnage0216

2021/02/15 03:57

ありがとうございます。 エピスさんノ str[i] は *(str + i) と同義です。なので iが変化すれば、当然ながら str+i は変化します。 # strは変化してません、固定値です。 について、&str[i] はアドレスの指す配列を表すので変数iで繰り上げてアドレスを上げるのに、なぜstr[i]だけなのですか?str[i]だけではアドレスの数値を上げられないと思います。
episteme

2021/02/15 04:01

↑本コメント欄で語ることではありません。fanaさんに失礼でしょう。
carnage0216

2021/02/15 04:07

エピスさんノ解答がわかりにくいためです。
episteme

2021/02/15 04:12

本コメント欄で語ることではありません(再度)
fana

2021/02/15 04:21

配列の要素はメモリ上で並んでいる. 仮に,char型のサイズが 1 バイトだとすれば, 配列の先頭の要素のアドレス値が仮に 1000 だったとしたら 2つ目の要素のアドレス値はその隣の 1001 である. 3つ目の要素のアドレス値はさらに隣の 1002 である. str とだけ書くと,これは先頭の要素のアドレス値という意味である.この例ではその値は 1000 だ. じゃあ (str+i) と書いたら,それはどんな値になるのだろうか? i=0 のとき, (str+i) = 1000 だ.これは先頭の要素のアドレスだ. i=1 のとき, (str+i) = 1001 だ.これは2番目の要素のアドレスだ. i=2 のとき, (str+i) = 1002 だ.これは3番目の要素のアドレスだ. 結局, (str + i) とは,「配列strのi番目の要素のアドレス」という意味だ. だから, *(str + i) とは,「配列strのi番目の要素」となる. で, > str[i] は *(str + i) と同義です ということなのだから,わざわざ *(str + i ) という形で書くかわりに,シンプルに str[i] と書けばそれで済む. だから str[i] と書けば良いだろう,というのがこの回答の趣旨である.
carnage0216

2021/02/15 04:31

丁寧な説明ありがとうございます。 では、&*(str + i) はstr+iと*(str + i)は同じなのですか? ん?*が付けばアドレスではなく、アドレスを表す数値をのですか? ならばCでは、&*str[i]は、str+iと全く同じ意味だと思うのですが。 正しいですか?違う場合は理由を教えてください。
fana

2021/02/15 04:37

なんかアドレス値があるとき, *(アドレス値) として * を頭につければ,「そのアドレスが指す場所にあるやつ」という意味. ここでは (str + i ) が i番目の要素を指すアドレス だから, *( str + i ) とは,「『i番目の要素を指すアドレス』が指す場所にあるやつ」だから,それは「i番目の要素」だ. 何か変数なりがあるとき, &(変数とか) として & を頭につければ,「その変数なりが存在するアドレス」という意味.
fana

2021/02/15 04:39

> &*(str + i) 前述のように, *(str + i) が「i番目の要素」なのだから, &*(str + i) とは,「i番目の要素 が存在するアドレス」である.その値は str + i と等しい.
carnage0216

2021/02/15 16:16

ありがとうございます。 ちなみにchar *p = &(str[0]); とはポインタの指す([0]の)アドレスの番号をポインタpの数値の列として代入するという意味でしょうか?
carnage0216

2021/02/15 16:46

もう一つ、 for( char *p=str; *p; ++p ) { ++(*p); } の処理過程を詳しく教えて下さい。ポインタのアドレスの指す変数pは++pにより増えて、++(*p)の++によりさらに増えるということでしょうか?
carnage0216

2021/02/15 17:23 編集

char *p = &(str[0]); について、実際にプログラムを書きました。 #include <stdio.h> int main(void) { char str[] = { "abcde" }; int i; char* p = &(str[0]); printf("%d\n", str[0]); } 結果は97と出ました。これは文字aを16進数で表したものなのでしょうか? また、処理内容はchar* p = &(str[0]);はポインタstrの表す([0]の)アドレスを渡す、しかしchar* p により、アドレスの番号ではなく、アドレスに入っている文字a(文字コード)が渡される。そして、 printf("%d\n", str[0]);により文字aを16進数?にした97とでた。ちなみに printf("%c\n", str[0]);としたらちゃんとaのみが結果で出ました。 私の説明は正しいでしょうか?
carnage0216

2021/02/15 17:38

#include <stdio.h> int main(void) { char str[] = { "abcde" }; for (char* p = str; *p; ++p) { ++(*p); printf("%d\n", *p); } } においては、char* p = strより、strに入っている文字列abcdeをchar* p により、ポインタのpの指すアドレスの番号ではなく、アドレスに入っている文字列abcde(文字コード)が渡される。 そして++pによりループして+1され、かつ、 ++(*p);の++によりもう一度+1される。 よって結果が 98 99 100 101 102 となる。
fana

2021/02/16 01:11

> ちなみにchar *p = &(str[0]); とは… Initialize the pointer variable p with the address value of the first element of the array str. > char *p = &(str[0]); について、実際にプログラムを書きました。 In this code, p is just initialized but not used. So, the presence of p has no effect.
fana

2021/02/16 01:27 編集

> for( char *p=str; *p; ++p ) > { ++(*p); } > の処理過程 "char *p=str" : p is initialized with the address value of the first element of the array str. "++(*p);" : As already mentioned, the description "*(address)" is "element pointed to by the address". Therefore, the target of incrementation "(*p)" is "the element pointed to by the current value of p". "++p" : Updates the value of p to the address value of the next element.
carnage0216

2021/02/16 06:40

日本語でお願いします。
fana

2021/02/17 04:26 編集

It looks like that no one can understand what you say, in Japanese. I was hoping that using another language would be the solution to this problem. But my attempt did not achieve anything... And now, there is no solution to communicate properly with you, I think.
fana

2021/02/17 04:25

Unfortunately, the only advice I can give is "use Japanese more correctly".
episteme

2021/02/17 04:33

I bet you're right.
fana

2021/02/17 04:42

(他人に対して「言葉を正しく使え」とか言ってるくせに,正しい英語を書けている気がしないという… "in Japanese" じゃなくて "with Japanese" とすべきだろうか?とか,いろいろと判断がつかぬ…)
episteme

2021/02/17 04:51

never mind. I believe such difference seems to be itsy-bitsy.
guest

0

&str[i]のアドレスを上げながらメモリに入った数値をそれぞれの値を+1したい場合は

悩むぐらいであれば、アドレスと中身の数値を別々にインクリメントすべきです。

「コードゴルフで1文字でも書くのが惜しい」など特殊な状況にないのであれば、インクリメントを式の途中に組み込むのは、可読性を下げるだけとなります。

投稿2021/02/15 02:12

maisumakun

総合スコア145967

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

carnage0216

2021/02/15 02:22

ありがとうございます。 二つ目の疑問については、なぜポインタのアドレス&str[i]とポインタの指すアドレスの中身のメモリに入っている変数iの数値を繰り上げるのに、 ++str[i++] または str[i++]++と&が付かず、 要は++&str[i++] または &str[i++]++という書き方ではないのか全く分からないのです。 なぜなら、str[i++] だけではポインタの指すアドレスの中身のメモリに入っている変数iの数値しか変わらないのでは?と思ったためです。
maisumakun

2021/02/15 02:24

> str[i++] だけではポインタの指すアドレスの中身のメモリに入っている変数iの数値しか変わらないのでは? iが変われば、str[i]が指すメモリ位置、つまり&str[i]が変化します。それで問題ないのではないでしょうか?
maisumakun

2021/02/15 02:26

というより、(一般的な状況を想定するなら)&str[i]で得られるアドレス値は、計算結果である「右辺値」です。右辺値をインクリメントすること自体が意味をなしません(「(i+3)++」と書くようなものです)。
carnage0216

2021/02/15 02:36

基礎の本を読んでも全然だめだとわかりました。 >>iが変われば、str[i]が指すメモリ位置、つまり&str[i]が変化します。 理解不足と基礎力不足でした。Cはそういうものなのでしょうか? ただ、例えば、メモリ1の数値が20だとして、iがインクリメントします。 そうするとメモリ1の数値は21となります。その時になぜ&str[i]まで変化するのかわかりません。 だって、、、 あれ、str[i]はiを含む配列ですよね?ってことはiの数値が変わるとstr[1]の時の配列のポインタのアドレスを1234として、iがインクリメントすると配列の位置も変わるため配列のポインタの指すアドレスが1235になる。 だから++&str[i++] または &str[i++]++と書く必要ながないというか++str[i++] または str[i++]++と書くだけでいいのですね。余談ですが++&str[i++] または &str[i++]++と書いてもいいのでしょうか?
maisumakun

2021/02/15 02:37

> メモリ1の数値が20だとして、iがインクリメントします。 そうするとメモリ1の数値は21となります。 なりません。
maisumakun

2021/02/15 02:38

> その時になぜ&str[i]まで変化するのかわかりません。 Cでは、&str[i]は、str+iと全く同じ意味です。
maisumakun

2021/02/15 02:41

やりたいことは、「iを変えてstr[i]が示す位置を動かしていきたい」のか「str[i]の中身を変更したい」のか、両方なのか、どちらでもないことを望んでいるのか、一体どれなのでしょうか? carnage0216さんの望むゴールが見えないので、何をしていいのかわからないです。
maisumakun

2021/02/15 02:49

では、i++とstr[i]++をそれぞれ行えばいいだけです。
carnage0216

2021/02/15 02:49

str+iより、strは配列の変数で、(*pとも出来て)、なぜそこに変数iを足すと っていうか、なんでそんなでたらめな形でもちゃんと動くのか。。。 > メモリ1の数値が20だとして、iがインクリメントします。 そうするとメモリ1の数値は21となります。 なりません。 えと、変数iの値がインクリメントされるのになぜ21にならないのですか?だとしたら何がインクリメントされるのですか?
maisumakun

2021/02/15 02:54

> えと、変数iの値がインクリメントされるのになぜ21にならないのですか?だとしたら何がインクリメントされるのですか? 「メモリ1」は「変数iが格納されているメモリ」を想定したものだったのですか?
maisumakun

2021/02/15 02:56 編集

> strは配列の変数で、(*pとも出来て)、なぜそこに変数iを足すと っていうか、なんでそんなでたらめな形でもちゃんと動くのか。。。 C言語の文法上、「ポインタ+整数」は「ポインタを整数だけずらした場所を指すポインタ値」という演算となっています。でたらめなのはcarnage0216さんの理解の方です。
carnage0216

2021/02/15 02:59

>>「メモリ1」は「変数iが格納されているメモリ」を想定したものだったのですか? そうです。
maisumakun

2021/02/15 03:05

てっきりstrの方のメモリだと解釈していました(なお、ローカル変数はレジスタに割り当てられてアドレスとして存在しないこともありえます)。
carnage0216

2021/02/15 03:06

C言語の文法上、「ポインタ+整数」は「ポインタを整数だけずらした場所を指すポインタ値」という演算となっています。でたらめなのはcarnage0216さんの理解の方です。 なるほど、そういう文法ゆえのルールだったのですね。。。 おっしゃる通りでたらめなのは私です。 >>&str[i]は、str+iと全く同じ意味です。 そうか、変数iが変化すると、iが変われば、str[i]が指すメモリ位置、つまり&str[i]が変化するため、ポインタの指定したメモリ(配列)も変化するのですね。 ちなみに、&str+iと書いた場合は、二度手間(iが変われば、str[i]が指すメモリ位置、つまり&str[i]が変化する)になるためおかしな結果が出るのでしょうか?
carnage0216

2021/02/15 04:14

str[i] は *(str + i) と同義です。なので iが変化すれば、当然ながら str+i は変化します。 # strは変化してません、固定値です。 ですが、&str[i] はアドレスの指す配列を表すので変数iで繰り上げてアドレスを上げるのに、なぜstrだけなのですか? &*(str + i) でないのかわかりません。
maisumakun

2021/02/15 04:18

> なぜstrだけなのですか? 何が「strだけ」と主張したいのですか?
maisumakun

2021/02/15 04:19

> &*(str + i) でないのかわかりません。 &*(str + i) はstr+iと全く同じ意味です。逆参照してからアドレスを取るという操作を省略しただけです。
carnage0216

2021/02/15 04:29

では、&*(str + i) はstr+iと*(str + i)は同じなのですか? ん?*が付けばアドレスではなく、アドレスを表す数値をのですか? ならばCでは、&*str[i]は、str+iと全く同じ意味だと思うのですが。 正しいですか?違う場合は理由を教えてください。 混乱してきました。
maisumakun

2021/02/15 04:33 編集

> ならばCでは、&*str[i]は、str+iと全く同じ意味だと思うのですが。 正しいですか?違う場合は理由を教えてください。 str[i]はポインタではないので、それに対して逆参照することはできません。
maisumakun

2021/02/15 04:34

> では、&*(str + i) はstr+iと*(str + i)は同じなのですか? *(str + i)は逆参照した後のままになっているので別物です。
carnage0216

2021/02/15 05:13 編集

別物というか、&*(str + i) は存在しない書き方ですね。 なぜなら「str」自体が既に先頭のアドレスを表すため str+iは変数iが+1増えると上に書いたようにstrは先頭のアドレスを表すため、アドレスも+1増えるわけですね。 (str + i)は*より数値を表すのでstrは「str」自体が既に先頭のアドレスを表すので、iが+1するたびにポインタのアドレスのメモリの数値も+1されるわけですね。なので
maisumakun

2021/02/15 04:55 編集

> 別物というか、&*(str + i) は存在しない書き方ですね。 いえ、&*を書いても無駄ですが、成立はします。
carnage0216

2021/02/15 05:13

>>ならばCでは、&*str[i]は、str+iと全く同じ意味だと思うのですが。 &*str[i]は&が付いているので、変数iが増えると*str[i]のポインタの指すアドレスに入っている数値に+1増えると思ったのですが、&と*とstrではなくstr[i]が同時にあるのでわからなくなりました。なので &*str[i]は存在する形なのでしょうか? >>*(str + i)は*より数値を表すのでstrは「str」自体が既に先頭のアドレスを表すので、iが+1するたびにポインタのアドレスのメモリの数値も+1されるわけですね。なので
carnage0216

2021/02/15 05:16

え!?&*(str + i) は無駄なのに成立するとはどういうことですか? &によりアドレスを示すので、またstrは「str」自体が既に先頭のアドレスを表すと思いきや*があるのでアドレスではなく、アドレスの指す値を示しているのかわからないです。どうかわかりやすく解説してください。
maisumakun

2021/02/15 05:17

> &*str[i]は存在する形なのでしょうか? すでに、「str[i]はポインタではないので、それに対して逆参照することはできません。」(つまり、「*str[i]」の時点で評価できない)と書いています。
maisumakun

2021/02/15 05:19

> どうかわかりやすく解説してください。 ・(str+i)…strからi進んだ場所を指すポインタ ・*(str+i)…str+iを逆参照した左辺値 ・&*(str+i)…上の左辺値のアドレス、つまりstr+i
carnage0216

2021/02/15 05:26

ということは書くことはできるけど、書いても意味不明になるだけのものなのですね。 *str[i]はポインタではないし、&もあって意味不明なのですね。 ということでしょうか?
maisumakun

2021/02/15 05:28

> ということは書くことはできるけど、書いても意味不明になるだけのものなのですね。 「コンパイルできない」ものを「書くことはできる」と主張するならそうなります。
carnage0216

2021/02/15 05:55 編集

*(str+i)…str+iを逆参照した左辺値 は上より、*(str + i)は*より数値を表すのでstrは「str」自体が既に先頭のアドレスを表しますが*よりポインタで指定されたアドレスのメモリの値を表す。そして、iが+1するたびにポインタのアドレスのメモリの数値も+1されるわけですね。(アドレスのメモリの数値が上がるだけでアドレスに変化はないため上に書いたままでしかない) &*(str+i)…上の左辺値のアドレス は左辺を優先するため、&が優先され、*はなくなるんで、アドレスを表す。変数iが+1増えるとstrのアドレスも+1されていく。(そして、配列よりアドレスが+1されたので、次のアドレスに値が入るわけですね。) なので書き方としては、 str+iに関しては、「str」自体が既に先頭のアドレスを表し、変数iが+1されることによってアドレス+1されるのでstr+iは&*(str+i)と同じというわけなのですね。 正しいですか?
carnage0216

2021/02/15 05:46

str[i] と*(str + i) と同義なのは、str[i] は値を扱うので、変数iが+1されるとstr[i]のアドレスの値も+1されるため、書き方として*(str + i)と同じと言える。
episteme

2021/02/15 05:58

むしろ逆です。 変数iが+1されるとstr[i]のアドレスの値も+1されるのは str[i] と*(str + i) および &str[i] と str + i が同義だからです。
carnage0216

2021/02/15 11:37 編集

あれ、 &str[i] は&がついてるからアドレスの値ではなく、アドレス自体を+1するから違うのでは? *str[i] なら他の三つと同じですが。 およびって「かつ」って意味だけど str[i] と*(str + i) と&str[i] と str + i が同義って意味ですよね? 新しい質問でがは違うとなりましたが。
carnage0216

2021/02/15 06:24

ってことは。str[i] と*(str + i) および &str[i] と str + iと&*(str + i) は同義?
maisumakun

2021/02/15 06:24

> &str[i] は&がついてるからアドレスの値ではなく、アドレス自体を+1するから違うのでは? これ自体に「+1」する作用はどこにもありません。そこまで紐付けて意味不明になっているので、足し算をする話はいったん置いておきましょう。
carnage0216

2021/02/15 06:33

出来ればiが+1される場合も考慮して str[i] と*(str + i) および &str[i] と str + iと&*(str + i) は同じですか? 仮にiを+1していくとして、 iが+1されるとstr[i]のポインタのアドレス自体ではなく、 アドレスに入っているメモリの値が+1され、 iが+1されるとつぎのアドレスに移行すると聞いたのですが、それは上の5つのうちどれですか? また、が+1されるとstr[i]のポインタのアドレス自体ではなく、 アドレスに入っているメモリの値が+1され、のは5つのうちどれですか?
maisumakun

2021/02/15 06:52

> iが+1されるとつぎのアドレスに移行すると聞いたのですが それは「アドレス演算そのものの性質」です(5つ全てに共通します)。
maisumakun

2021/02/15 06:53

> また、が+1されるとstr[i]のポインタのアドレス自体ではなく、 アドレスに入っているメモリの値が+1され、のは5つのうちどれですか? (未定義な動作に突っ込んだ場合を無視するなら)どれでも起きません。アクセスしただけでメモリの中身が変化するkとおはありません。
carnage0216

2021/02/15 16:18

>>悩むぐらいであれば、アドレスと中身の数値を別々にインクリメントすべきです。 に関して、どのように別々にインクリメントすればよいのでしょうか?
episteme

2021/02/15 17:28

いや、だから str[i]++ と i++ だってば。
guest

0

str[i]++;
i++;

ではダメなんでしょうか。
ダメな理由はなんでしょうか

投稿2021/02/15 02:06

y_waiwai

総合スコア88038

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

carnage0216

2021/02/15 02:22

ありがとうございます。そうではなく、変数iの数値の上げ方の書き方はわかるのです。 二つ目の疑問については、なぜポインタのアドレス&str[i]とポインタの指すアドレスの中身のメモリに入っている変数iの数値を繰り上げるのに、 ++str[i++] または str[i++]++と&が付かず、 要は++&str[i++] または &str[i++]++という書き方ではないのか全く分からないのです。 なぜなら、str[i++] だけではポインタの指すアドレスの中身のメモリに入っている変数iの数値しか変わらないのでは?と思ったためです。
carnage0216

2021/02/16 06:42 編集

++str[i]; i++;だとしても++str[i];の++は必要ですか? i++でstr[0],str[1],str[2]...と(配列の)アドレスが上がっていくのでstr[i]; i++;だめでいいのでは?と思っています。
guest

0

str[i]が指し示す位置を動かしつつ、str[i]の中身を変えたいということであれば
以下のように書けばいいだけなんだけど。
↓の例では配列の中身を全て0で初期化しているので出力結果は全て1になります。

C

1#include <stdio.h> 2int main(void){ 3 int i; 4 int str[5]={0}; 5 6 for (i = 0; i < 5; i++){ 7 str[i]++; 8 printf("%d\n", str[i]); 9 } 10}

そもそも配列の指し示す位置を動かす為に&を付ける必要があるという思い込みが
間違っていて、単純にstr[0]、str[1]、str[2]としていけば指し示す位置を
変更出来るということが理解出来ていないのかな?

投稿2021/02/15 02:51

kaina

総合スコア418

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

carnage0216

2021/02/15 02:56

以前にカズマさんが&を付けることでポインタの表すアドレスを変更できると聞いたもので、思い込みをしてしまったのかもしれません。 >>p は &str[i]、*p は str[i]、 q は &str[j]、*q は str[j] という関係です。
episteme

2021/02/15 03:00 編集

あなた 「*p は忘れろ」って言わなかったっけ?
carnage0216

2021/02/15 02:58

ちなみに、 >>iが変われば、str[i]が指すメモリ位置、つまり&str[i]が変化します。 理解不足と基礎力不足でした。Cはそういうものなのでしょうか? について、Cがそのようなものであるため、変数iが変化すると配列のアドレスも変化するのでしょうか?
episteme

2021/02/15 03:04 編集

str[i] は *(str + i) と同義です。なので iが変化すれば、当然ながら str+i は変化します。 # strは変化してません、固定値です。
carnage0216

2021/02/15 03:38

なるほど、設計者がそのように開発したからなのですね。 ですが、&str[i] はアドレスの指す配列を表すので変数iで繰り上げてアドレスを上げるのに、なぜstr[i]だけなのですか?str[i]だけではアドレスの数値を上げられないと思います。
episteme

2021/02/15 03:52 編集

> str[i]だけではアドレスの数値を上げられないと思います。 はい、その通りです。 あなたが正しく理解できていないのか、自らの理解を文章で表現できないのか、あるいはその両方か。 おそらく僕を含むすべての回答者は判断できずに困惑している(なにがわからないのかわからない)と感じます。
carnage0216

2021/02/15 03:59

あの こちらの質問に答えて頂けないですか? &str[i] はアドレスの指す配列を表すので変数iで繰り上げてアドレスを上げるのに、なぜstr[i]だけなのですか?
kaina

2021/02/15 04:00

>ですが、&str[i] はアドレスの指す配列を表すので変数iで繰り上げてアドレスを上げるのに、なぜstr[i]だ>けなのですか?str[i]だけではアドレスの数値を上げられないと思います。 あなたの思い込みは関係ありません。 仕様がそうなっていたら、それが全てです。
episteme

2021/02/15 04:10 編集

> こちらの質問に答えて頂けないですか? > &str[i] はアドレスの指す配列を表すので変数iで繰り上げてアドレスを上げるのに、なぜstr[i]だけなのですか? 「&str[i] はアドレスの指す配列を表す」と「変数iで繰り上げてアドレスを上げる」が、 何が言いたいのかわからないので答えようがありません。 str[i] は「配列strのi番目の要素」です。それをインクリメントするのなら ++str[i] とか str[i]++ とか str[i] = str[i] + 1 とするでしょう。これの何がわかりませんか?
carnage0216

2021/02/15 04:08

どうせ私の質問は意味不明でしょうから、もう答えなくていいですよ。 余計に話を難しくするし、
episteme

2021/02/15 04:17

「私の質問は意味不明ですから、理解できる人だけ答えてください」とでも?
carnage0216

2021/02/15 05:36

だって、エピスさんノ日本語が専門用語すぎて難しいんだもん。
episteme

2021/02/15 05:48 編集

↑たとえば、どれですか? 必要なら言い換えますが。 そのことと「私の質問は意味不明」との間に何の関係がありますか?
fana

2021/02/15 11:02

ひょっとしたら,互いに英語を用いたりとかすれば言葉の壁の問題がクリアされるのかもしれない. > str[i] は「配列strのi番目の要素」です。それをインクリメントするのなら ++str[i] とか str[i]++ とか str[i] = str[i] + 1 とするでしょう。 ↓(翻訳に自身がないけど)こんな感じで. str[i] is the "i-th element of the array str". If you want to increment the value of the element, you can use one of the following: ++str[i] str[i]++ str[i] = str[i] + 1
episteme

2021/02/16 01:14

>> だって、エピスさんノ日本語が専門用語すぎて難しいんだもん。 > ↑たとえば、どれですか? 必要なら言い換えますが。 > そのことと「私の質問は意味不明」との間に何の関係がありますか? これに答えていただけませんか? 僕に改善すべきことがあるなら考慮したいので。
kazuma-s

2021/02/16 05:05

> 以前にカズマさんが&を付けることでポインタの表すアドレスを変更できると聞いたもので、思い込みをしてしまったのかもしれません。 「&を付けることでポインタの表すアドレスを変更できる」というのは いつ誰が言って誰が聞いたのですか?
carnage0216

2021/02/16 05:17

いえ、私の勘違いでしたすいません。
kazuma-s

2021/02/16 05:58

では、「& は何に付けるのか、付けるとどうなるのか」を説明してください。
carnage0216

2021/02/16 06:08

はい、&は変数にアドレスを付けたいときに使用します。 例えば int main(void){ int *p,i; p = &i; return 0; }のようにiのアドレス値をポインタのアドレスに入れたいときなどに使うと考えています。
carnage0216

2021/02/16 06:09

またお時間のある時で構いませんので。以下の質問に答えて頂けないでしょうか? &(*p)と&*(str + i)に*をつけるのはなぜですか? ポインタのようなアドレスを表すならば、*はいらないと思うのですが。 要は&(*p)と&(str + i)でいいのでは?と考えてしまいます。 なぜ*をつけるのですか?わかりやすく詳しく教えてほしいです。
kazuma-s

2021/02/16 06:20

「変数にアドレスを付ける」この表現は間違いです。 変数にはアドレスが無かったのに、& を付けると変数がアドレスを持つようになるのですか?
carnage0216

2021/02/16 06:30

>>& を付けると変数がアドレスを持つようになるのですか? はい。。。苦しんでCにはそう書いてありました。
kazuma-s

2021/02/17 00:11

「& は何に付けるのか、付けるとどうなるのか」を説明してください。
kazuma-s

2021/02/17 00:14 編集

「* は何に付けるのか、付けるとどうなるのか」を説明してください。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問