複雑な形式と言っても、上の図でint (*a)[3];とint* b[3]です。ネタ本ではsizeof(…)の例だけで、なんか分かりづらい。少しだけ、噛み砕いてみました。昔見た本で、今は処分してないのですが、ポインタはいくらでも複雑怪奇に書けるみたいです。
func(int (*a)[3])となってるのに、a[2][2]=100;となってるので、ポインタaで渡してる意味が半減です。その下のコメントアウトしてる部分なら、意味ありそうではないでしょうか?
実行結果は同じです。エラーメッセージはデバッグをしないと変わらないので、直したらビルドかデバッグをします。
iptrはintへのポインタです。&a[i]はintの配列(大きさ3)へのポインタです。タイプが違うので(int *)&a[i];でキャストしないとワーニングが出ます。
配列形式a[i][j]のほうが従来の書き方と一致しますので、気分的には楽です。
二次元の配列に値をセットします。a[i][j]形式でアクセスします。
int* iptr=&a[0][0]でポインタをセットします。二次元配列は無いのだそうですので、*iptr++で次々セットしていきます。
上はネタ本の通りです。unsignedの場合は、純粋のメモリのアドレスの計算になるようです。ポインタの場合は、この場合は+1でアドレスは+4するようです。int32を使ってるようです。
大きな違いは、x[0]のアドレスをポインタにセットの仕方が違います。Cではp=&x[0]、多分int* p=&x[0];でも良いと思います。C#では、int *p=(int *)x[0];と書いてます。なんで&が無いんですかね?C#では参照渡しのとき使っていたはずです。
上の図の通りで実行できるんですが、コンパイラは別の書き方に訂正したいようです。C言語とC#の違いですが、int *p, *q;と書けるのが、C言語。int *p; int *q;と書かないといけないのがC#のようです。
ネタ本では、コメントアウトしている部分です。for文でもだいたい同じと思います。
前回C#の例をやってみましたが、関数がstaticだったので、メンバー関数(メソッド)にしてみました。C#の場合は、基本ポインターを使わないようです。どうしても使う時は、unsafeを付けるようですが、プロジェクトのプロパティをunsafeを許可しますにチェックする、なかなかコンパイルが通りませんでした。(´°̥̥̥̥̥̥̥̥ω°̥̥̥̥̥̥̥̥`)
コンパイルが通っても、実行時エラー。何でだ?CとC#では考え方違うんだろうか?
難しい所はないでしょう。C言語にはmod関数は、無いようです。また、C言語だと、オブジェクトの概念が多分ないので、構造体は有るようですが、多分ですが、C#だとint a[100];となっていると、a.sizeとか書けるような気がします。なので、コピーする個数を指定しないといけない。
確かに、C#だと配列の大きさを知ることは出来ますね。a.Lengthでした。sizeを使う言語とLengthを使う言語が有るようです。
自分は、debuggerを使わないと出来ない人ですので、Visual Studio 2019でやりました。VS Codeと両立が少しおかしくなるのですが、なんとかなります。
書きながら思ったんですが、本ではstrcatという名称を使ってます。#include 書いてないので、エラーにならないような気がしますが、どうですか?putsの行は、本では2行になってますが、後も書けるはずでやってみました。whileの中、比較してませんね。よく理解してないと書けないですね。
やはり関数名、strcat使えました。
エリアが十分無いと、上記の実行時エラーが起きるようです。
上の図では、配列の大きさを十分?取ってます。そうするとエラーは起きません。strcatはstrへのポインタを返すようです。本には教訓があります。
必要な記憶領域は、自分で確保しなければならない。
ネタ本では、intが何バイトか?書いてませんが、2バイトなんでしょうね。但しVS Codeでは4バイトだと思います。size_t即ちunsigned intは0から65535迄を表現できるとあります。下の表では2の16乗と一致します。サンプルのプログラムは、限界を超えたらどうなるの?の例ですが、此の場合、超えてないので、どちらも正常に処理されてます。ポインタ間の演算はsigned intと定義されているので、-32768から32767までが扱う範囲ということです。
ネタ本では両方とも-32536と表示されると、あります。
#includeで関数を取り込む時は、プロトタイプは必要なかったですが、分割コンパイルだと必要のようです。
メニューから実行で、実行ファイルできるんですかね?駄目ですね。分割コンパイルの場合は、ターミナルから行わないと出来ないようです。
#include "Mystrlen1.c"なので、取り込んでるんですよね。コンパイルはその後でしょうから、正確には分割コンパイルと言わないかも知れません。gcc -o program list2-13.c mystrlen1.cとターミナルから、コンパイルは出来ると思います。こっちは分割コンパイルと言えるでしょう。
但し、#include "Mystrlen1.c"と書いてあれば、gccではmystrlen.cは要らないです。有ると二重に定義しているとエラーが出ます。
#includeはfoo.cもinclude出来ますが、一般的にはfoo.hが普通かもしれません。
別ファイルのMystrlen0.cを取り込むのに、#include "Mystrlen0.c"で行けますね。これをやらない時はgcc -o proram list2-12.c mystrlen0.cでも行けました。 Mystrlen0.cのプロトタイプは付けました。必須かどうか?
前回、ローカル変数を返してはいけないと、間違って書きました。上の図でreturn i;はローカル変数です。正確には、ローカル変数のアドレスを返してはいけない、です。
VS Codeで同じホルダーでは、cとcppが混在していると、上手く出来ないのかも?知れません。今回はcppの例ですので、なんとか動かせる、VS 2019でやってみました。ネタ本はハーバード・シュルツさんの「独習C++」の例からです。上の図の例で16行から21行までは、なんとなく、ローカルの変数tempを返しているように見えるんですが、前回の例とは違うんでしょうね。
前回の例と同じものを追加してみました。おかしな文字が表示されてます。文字列をstaticにしてみます。
今回は正解の文字(abcdef)が表示されてます。演算子のオーバーロードでは、関数のように見えても関数ではないのかも知れません。メンバー関数またはメソッドなんですかね?