読者です 読者をやめる 読者になる 読者になる

call by value, call by reference?

気になったのが、配列は関数に渡す事が出来ない。ってのも、失念していたかも。
値渡しが出来ない。って意味なんだろうけれど、これも、配列を値渡ししようと思ったことがないので、気にしたことがなかった・・・

配列を何かしたいときは、disp_pointerな感じになるかな。こういう使い方自体が間違ってる?
どちらの関数も参照渡しかな。
dip_arrayは、nt items[] で受け取れるのかな?ってやってみたら、受け取れたので書いてみた。
配列の中身を変更させようとしたら、変更できたので通常の参照渡しになっているみたい。

Javaのあとだと勘違いしがちなこと。
call by value, call by reference.
(前にきむら(K)さんにcall by nameもあると言われた記憶が)

まず最初に、
Cには参照渡しはありません。
値渡しだけです。
故に値を変えたい場合はポインタの値渡しです。


C++には値渡しと参照渡しがあります。
ただし、参照渡しは多くの場合値渡しのコスト軽減やポインタよりもセーフティになるために使われます。
出来うる限りconstをつけた方が良いでしょう。
(出力パラメータなどに使うと見た目にわかりづらいため)


Javaには参照渡しはありません。
値渡しだけです。「参照」を値渡ししています。


で、とりあえず、
「Cでは配列は渡すことができない」
arraypointer.c
で書かれているdisp_array(int items[])は、
disp_array(int* items)
のSyntaxSugar(構文糖衣)にすぎないです。

実証するのは簡単で、

void func(int dummy[], int length)
{
    printf("func:\n");
    printf("sizeof(dummy):%d\n", sizeof(dummy));
    for (int i = 0; i < length; ++i) {
        printf("%d,",dummy[i]);
    }
    printf("\n");
}

int main()
{
    int dummy[] = { 1, 2, 3, 4, 5, };
    printf("sizeof(dummy):%d\n", sizeof(dummy));
    func(dummy, sizeof(dummy)/sizeof(dummy[0]));
    return 0;
}

で、

sizeof(dummy):20
func:
sizeof(dummy):4
1,2,3,4,5,

という結果が得られます。
関数に渡す前はsizeofは配列のサイズを返すけれども、
関数に渡ったあとはsizeofはポインタのサイズを返す。
main側のdummyは配列なのに、
func側のdummyはポインタになってしまっている。

なので、これは「参照渡しでもなんでもない」です。

さらに詳しくは多次元配列を渡そうとすると解る筈。
int dummy2[3][3] = ...
を渡したいなら、
void func2(int dummy[][3])
と書きます。
void func2(int **dummy)
では渡せません。
色々詳しくはきむら(K)さん
参照のこと。

配列の中身を変更させようとしたら、変更できたので通常の参照渡しになっているみたい。
これは今までやったことがないから、どういう風になっているのか調べてみないとだなぁ

実際、動作を理解していると思っていても、
細かい動作をさせてみるとそれが理解とは違っていることが多々あります。
そして、それが思惑通りだったとしてさえ、
違うことがあります。

これがCの難しさなのかもしれません。
C FAQ も読むと良いです。
http://www.kouno.jp/home/c_faq/c6.html

ここね。
同じ様にメモリ演算してくれる物。って意味に、訂正で・・・

ということで、
同じように見えるものが同じだとは限らない、ということでした。
Cでは、

// ATOKで変換したらまたHalloに!!!! > きむら(K)さんへのレスポンス
// K&R的には hello, world
char message[] = "Hallo, World!!!";

printf("[%c]\n", 1[message]);

こんな風にも書けてしまうわけで、
これが誤解の元なのかもしれませんねえ。
1[message]ってなんだよ、みたいな。
あと、
void func(int& dummy[]);
みたいなこともできません。
これじゃ、参照の配列みたいだけど。

C++でも、関数の中で値を変更されたくない時は、きちんと const を付けて引数指定しなさい。って事かな。

C++では
constな引数だけではなく、constなメソッドを使うことで、
メンバ関数の中でそのオブジェクトの状態が変更されない事を保証することができます。
mutableやconst_castもあるのでその限りではありませんが、
これを意識するとC++での設計が綺麗になると思います。