C言語 / C++ / C# の勉強 ~ C/C++ 私の勝手な「ポインタ / 変数」の解釈

C言語 / C++ / C# の勉強中

1週間以上あいてしまいましたね…。
PCをしていたことはしていたのですが、プログラミングがはかどらず、時間が空いてしまいました…。
C#のオブジェクト指向に苦しむ。
C++でもオブジェクト指向使うしなぁ…。まあとりあえず頑張ります。
名前空間=HSPでいうモジュール空間的な?
オブジェクト=命令や変数をまとめたもの?C++だと構造体と同じ扱いらしい。
メソッド=オブジェクトについてる関数
プロパティ?=これいろいろな意味あると思うけど、オブジェクトについてる変数でおk?
クラス=オブジェクトの設計図。変数でいう構造体定義みたいなもん
インスタンス化=クラスからオブジェクトを作ること?変数でいうただの変数定義みたいな (でも、必ず定義したときに作成されるとは限らない?)
コンストラクタ=インスタンス化時に初期化する内容をまとめたもの?クラス名やオブジェクトの型名?と同じ名?

C/C++ 私の勝手な「ポインタ / 変数」の解釈

すんなりわかる人はわかるんでしょうけど、私はなかなか理解できませんでした。
そもそも変数の定義の仕組みがよくわかってませんでした。

char var1;
short var2;
long var3;

上のソースコードは、1バイト、2バイト、4バイトのメモリを確保するものです。これは誰でもわかりますよね。

それでは

char var1=0x09;
short var2=0x2525;
long var3=0x35F02100;

上のは?初期値を代入しているだけですね。

じゃあ、変数定義時に*をつけたり関数の引数として指定したり&をつけたりすると…?それと配列変数とかは…?
そこでわからなくなりました。

int var;
int* ptr=&var;

これは、「&var」でvarの場所 (ポインタ) をだし、それを(int*)型の変数ptrに代入しています。

ポインタ変数で初期値を設定した場合、intだとか*だとかをつけていない、すっぴんの変数に代入されます。「*ptr」に代入されたりはしません。関数での引数定義でも同じです。
次に配列変数

int var[10];
int* ptr=var;

実は、配列変数はポインタ変数と同じような扱いなのです。いや、むしろ同じものと言っていい。

上のソースで、varは、「&」をつけなくても変数varのポインタを表してくれます。
それどころか、使い方だって同じようにできます。

char var[10]={0,1,2,3,4,5,6,7,8,9};
char* ptr=var;

の時、たとえばvar[6]と*(ptr+6)は同じ値を返します。アドレスに配列6個分すすめたところを取得しているわけです。注意しなければいけないのは、ここでの「変数+~」は、ポインタの単純な足し算ではないことです。ここではcharを使ったので問題ありませんが、int型とかだと、アドレスに指定した数*一つ当たりのサイズがたされ、それから取得されます。

さて、ここからが本題。(というほどのものでもないんだけれど)

int var1=0;
int* var2=&var1;
int** var3=&var2;
int*** var4=&var3;

これはそれぞれどういう意味なのでしょうか?
一番上は単純に変数の定義です。実は2番目以降は、型こそ違えど中身は同じです。どれもただアドレスを入れているだけです。
char*も、short*も、int*も、名前・型が違うだけで同じです。アドレスを入れるための変数というだけです。
int型の変数のアドレスだから(int*)型、(int*)型の変数のアドレスだから(int**)…という感じです。
あと、このとき、var4という変数は、(int***)型であり、*var4は(int**)型であり、**var4は(int*)型で***var4はvar1を表すことになります。
参照渡しで使う「int *&var」とかいう表記は。varのポインタに*をつける、つまりvarの変数そのものを表します。代入とかは、var=値;でおkです。そりゃそうですよね。値の型だけ考えたら(int *&)=(int)だもの
以上、勝手な私の解釈でした。


「C言語 / C++ / C# の勉強 ~ C/C++ 私の勝手な「ポインタ / 変数」の解釈」への4件のフィードバック

  1. 特に大きな間違いは無さそうですね。
    静的配列変数を絶対にポインタと同じだというような解釈をしないほうがいいです。理論としてはあってますが、宣言もint[n]などと通常のポインタ変数と区別して、それが配列であることを型レベルで明示しておくべきです。
    それから、ポインタ演算は基本的にしないほうがいいです。知識としてはあったほうがいいですけど、実用するとソースが読みにくくなって開発効率が落ちます。

  2. >静的配列変数を~
    いや、そう思わないとポインタを理解できなかったからそう書いているだけで…別に実際は混ぜようとは思っていません。だから
    int var[10];
    int* ptr=var;
    varとptrで分けたんですよ。
    ptrにvarのポインタを入れてるのは、ほかの変数定義が面倒くさかったからです。実用のソースコードではないので。

    >ポインタ演算は基本的に
    そりゃあまあ今回は型を説明するためだけにネタでポインタのポインタのポインタを使っただけで…普段はこんな変なことはしませんよw
    必要なときやソースが書きやすくなるようなときに使ってます。

    指摘ありがとうございました。

  3. お久しぶりです!
    >参照渡しで使う「int *&var」とかいう表記は。varのポインタに*をつける、つまりvarの変数そのものを表します。
    int *&varってどのような状況で使うのでしょうか。
    intをつける時と言いますと、関数の宣言の引数のところか、変数の宣言くらいしか思いつきませんが、いずれにせよ、int *&varというときの「&」というのはvarのアドレスを出さずにreferenceという意味になり、結局の型は(int *&)型です。
    これはintというよりはむしろ(int *)型と思ったほうが近いような気がします。

    int main(void)
    {
    int a = 0;
    int *b = &a;
    //int *&var = a; error!
    int *&var = b;
    return 0;
    }

  4. ああう、関数の引数でないときはそう使うのですね。
    まだまだ未熟でごめんなさい。ためになりました!

コメントは受け付けていません。