自作関数でアドレスを呼び出した時

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

自作関数でアドレスを呼び出した時

#1

投稿記事 by ぜり » 13年前

#include <stdio.h>
int i;
int func(int x[]);

int main(void){
int a[4];
for(i=0;i<4;i++)
a=i;
printf("%d",func(&a[1]));
return 0;
}

int func(int x[]){
return x[2]+i;
}

初歩的な質問ですみません;
まずmain関数でa[0]=0,a[1]=1,…a[3]=3,そしてi=4で終わりになるのはわかりました
その後func関数を呼び出してますよね?
この時&a[1]なのでa[1]のアドレスをint x[]の方に入れていると思ったのですが
出力するとx[2]は3なので結果的に7が出力されています。

どう伝えれば良いか分からないのですが 何故アドレスを入れているのに結果としては
普通の数字が出力されているのでしょうか・・・

printf("%d",func(&a[1]));
return 0;
}

int func(int x[]){
return x[2]+i;
}
このあたりの処理を詳しく書いて頂けると助かります><

アバター
nullptr
記事: 239
登録日時: 13年前

Re: 自作関数でアドレスを呼び出した時

#2

投稿記事 by nullptr » 13年前

コードはタグで囲んでください。インデントも整えましょう。コードタグについて

数字が出るのはfunc関数は「int型を返す」ように書いてあるからです(int func( int x[] ))。そしてそのとおりにint型の実体をreturnしているからです(return x[2]+i;)。
引数としてアドレスを与えていたとしても、戻ってくる値がアドレスとは限らないです。
 
 
✜ で C ご ✜
: す + 注 :
¦ か + 文 ¦
?
Is the は :
order C++? ✜
     糸冬   
  ――――――――
  制作・著作 NHK
 
 

ぜり

Re: 自作関数でアドレスを呼び出した時

#3

投稿記事 by ぜり » 13年前

次から囲むように気をつけます><
すいませんでした;

int x[]には&a[1]のアドレスの値が入らずに
a[1]の値が入るということなのでしょうか?(x[]となっているのでa[1],a[2],a[3]の値も入っていくとは思うのですが)

正直そのあたりの理由がわかっていません…

アバター
nullptr
記事: 239
登録日時: 13年前

Re: 自作関数でアドレスを呼び出した時

#4

投稿記事 by nullptr » 13年前

ぜり さんが書きました:次から囲むように気をつけます><
すいませんでした;

int x[]には&a[1]のアドレスの値が入らずに
a[1]の値が入るということなのでしょうか?(x[]となっているのでa[1],a[2],a[3]の値も入っていくとは思うのですが)

正直そのあたりの理由がわかっていません…
いえ、ですからちゃんとxにアドレスは渡されていますよ。
返ってくるのが中身の値なだけです。
 
 
✜ で C ご ✜
: す + 注 :
¦ か + 文 ¦
?
Is the は :
order C++? ✜
     糸冬   
  ――――――――
  制作・著作 NHK
 
 

naohiro19
記事: 256
登録日時: 15年前
住所: 愛知県

Re: 自作関数でアドレスを呼び出した時

#5

投稿記事 by naohiro19 » 13年前

funcのiとmainのiは別扱いです。

ぜり

Re: 自作関数でアドレスを呼び出した時

#6

投稿記事 by ぜり » 13年前

アドレスは渡されているけども
int x[] というようにしているので
そのアドレスの中身が入っているという考えで大丈夫でしょうか
何度もすみませんorz

ぜり

Re: 自作関数でアドレスを呼び出した時

#7

投稿記事 by ぜり » 13年前

naohiro19 さんが書きました:funcのiとmainのiは別扱いです。
グローバル変数で定義しているので同じ物になるんじゃないでしょうか><

トントン
記事: 100
登録日時: 15年前

Re: 自作関数でアドレスを呼び出した時

#8

投稿記事 by トントン » 13年前

ぜり さんが書きました:次から囲むように気をつけます><
すいませんでした;

int x[]には&a[1]のアドレスの値が入らずに
a[1]の値が入るということなのでしょうか?(x[]となっているのでa[1],a[2],a[3]の値も入っていくとは思うのですが)

正直そのあたりの理由がわかっていません…
どういうイメージでいるのかわかりませんが

xには

//アドレスは適当
x[0]=0x1000
x[1]=0x1004
x[2]=0x1008



が入るイメージでいるということでしょうか?

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 自作関数でアドレスを呼び出した時

#9

投稿記事 by softya(ソフト屋) » 13年前

このプログラムだとfuncにa+1のポインタ値がxに受け渡されたので
a[1] == x[0]
a[2] == x[1]
a[3] == x[2]
と言う対応になっています。

>そのアドレスの中身が入っているという考えで大丈夫でしょうか
ポインタ値は変数の場所を指す値ですので、アドレスの中身という言葉はふさわしくないかなと思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ぜり

Re: 自作関数でアドレスを呼び出した時

#10

投稿記事 by ぜり » 13年前

トントン さんが書きました:
ぜり さんが書きました:次から囲むように気をつけます><
すいませんでした;

int x[]には&a[1]のアドレスの値が入らずに
a[1]の値が入るということなのでしょうか?(x[]となっているのでa[1],a[2],a[3]の値も入っていくとは思うのですが)

正直そのあたりの理由がわかっていません…
どういうイメージでいるのかわかりませんが

xには

//アドレスは適当
x[0]=0x1000
x[1]=0x1004
x[2]=0x1008



が入るイメージでいるということでしょうか?
まさにこれです
このような感じでイメージしていたのですが x[2]=3になっていたので
アドレスが入っていなくて…
で質問させてもらいました

ぜり

Re: 自作関数でアドレスを呼び出した時

#11

投稿記事 by ぜり » 13年前

softya(ソフト屋) さんが書きました:このプログラムだとfuncにa+1のポインタ値がxに受け渡されたので
a[1] == x[0]
a[2] == x[1]
a[3] == x[2]
と言う対応になっています。

>そのアドレスの中身が入っているという考えで大丈夫でしょうか
ポインタ値は変数の場所を指す値ですので、アドレスの中身という言葉はふさわしくないかなと思います。
ポインタ値(アドレス値)がxに渡された時にはx[0]=アドレス
となっているのでは無いのでしょうか?

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 自作関数でアドレスを呼び出した時

#12

投稿記事 by softya(ソフト屋) » 13年前

int x[]のxはポインタですがx[0]はintです。
&a[1]はa+1のポインタ値です。
なので、
int x[];
x = &a[1];
としているのと同じです。
x[0]では、&a[1]のポインタ値が指す値すなわちa[1]の値を参照します。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ぜり

Re: 自作関数でアドレスを呼び出した時

#13

投稿記事 by ぜり » 13年前

softya(ソフト屋) さんが書きました:int x[]のxはポインタですがx[0]はintです。
&a[1]はa+1のポインタ値です。
なので、
int x[];
x = &a[1];
としているのと同じです。
x[0]では、&a[1]のポインタ値が指す値すなわちa[1]の値を参照します。
自分の勉強不足で知らないのかもしれませんが
intとなるとそのポインタ値の示す値を参照するようになるのでしょうか?
この場合xだけだとポインタ値を参照するけれども
x[0]でintとなったので、ポインタ値が示す値を参照したということなんでしょうか…

追記で申し訳ないのですが int x[]で配列の大きさを指定していないので
a[1] a[2] a[3]まであるので x[0] x[1] x[2]まであるのですよね?

語彙が少なくて上手く伝えられなくてすみません

ISLe
記事: 2650
登録日時: 15年前
連絡を取る:

Re: 自作関数でアドレスを呼び出した時

#14

投稿記事 by ISLe » 13年前

そもそもC言語では配列そのものを引数にすることができません。
int func(int x[]);
と書くと
int func(int *x);
と解釈されます。

softyaさんが書いてますが、&a[1]というのはa+1です。
これを引数にしてfunc関数が呼び出されるとx[2]というのは(a+1)[2]→(a+1)+2→a+3→a[3]ということになります。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 自作関数でアドレスを呼び出した時

#15

投稿記事 by softya(ソフト屋) » 13年前

intだから値で参照するのではなく、xがint型のポインタで配列参照しているからint値として参照するのです。
x[2]としても、*(x+2)としても同じ場所の値を参照することが出来ます。

あとfuncに受け渡されるのはポインタ値だけなので配列の大きさについてはC言語は関与しません。
x[3]とやってもコンパイラは警告を出さず参照できますが、その値が何の変数の値なのかは環境と運次第としか言えませんし、メモリ範囲外で異常終了するかも知れません。

ISLeさんも書いてますが、C言語では配列を引数としたい場合はポインタ値しか受け渡すことができません。
PHP等の他の言語だと配列のコピーを受け渡すことも可能ですけどね。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

box
記事: 2002
登録日時: 14年前

Re: 自作関数でアドレスを呼び出した時

#16

投稿記事 by box » 13年前

コード:

#include <stdio.h>

int i;
int func(int *x);

int main(void)
{
    int a[4];

    for (i = 0; i < 4; i++) {
        a[i] = i;
    }
    printf("%d\n", func(&a[1]));
    return 0;
}

int func(int *x)
{
    return x[2] + i;
}
質問者さんが書かれたコードは、実質的に上と同じなわけです。

main関数では、func関数を呼び出す際の引数として、配列要素a[1](値は1)の
アドレス(値は1じゃないですよ。アドレスですから)を渡しています。

そのアドレスを受け取ったfunc関数では、そのアドレスを起点として2つ分離れた要素(x[2]って書いてますからね)の
場所に入っているint型の値(つまり3)に、グローバル変数iの値(4)を加えたint型の値(つまり7)をreturnしています。
よって、main関数のprintf関数の実行結果として、
7
という出力を得ます。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

ぜり

Re: 自作関数でアドレスを呼び出した時

#17

投稿記事 by ぜり » 13年前

今やっと頭の中の整理をして理解することが出来ました
int func(int x[]) は int func(int *x)と
書き換える事ができるのですね

これで理解することが出来ました!
皆さん長々とありがとうございました><
これで試験に臨めます;;

閉鎖

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