0

このプログラムは、3 桁の数字を取り込んで回文に変換することになっています。123になり321ます。

ロジックは正しく、プログラムは正しくコンパイルされます。:) ただし、これらのロジックは簡単にはわかりません。

私の教授は「スタック図」を使って物事を説明していますが、私はそれらが役に立つと思います. このプログラムと私が作成した別のプログラムとの類似性に気付いたので、別のプログラムに基づいてこのプログラムを作成しました、ポインティングはどのように機能しますか?

#include <stdio.h>

void reverse_number(int in_val, int *out_val) {
    int ones, tens, hundreds;

    ones = in_val % 10;
    tens = (in_val % 100 - ones) / 10;
    hundreds = (in_val - (ones + tens)) / 100;

    *out_val = (ones * 100) + (tens * 10) + hundreds;
}

int main() {
    int in_val;
    int out_val;

    printf("Give a three digit num to reverse: \n");
    scanf("%d", &in_val);

    reverse_number(in_val, &out_val);
    printf("New number is: %d \n", out_val);

    return 0;
}

また、これらのポインターを使用して一種のテンプレートに基づいてプログラムを作成する方法を理解し始めており、パラメーター内のスターが何を意味するか (ポインター変数として宣言されている) を非常に基本的に理解しています。

たとえば、変数に別の変数のアドレスをm = &q;与えることは知っていますが、それはアドレスの値が入ることを意味しますが、関数とメインファイルのコンテキストでこれらがどのように機能するかについては本当によくわかりません.mqm = *g;gm

誰かが (このプログラムで) それがどのように機能するかの基本的なロジックを説明できれば、それは素晴らしいことです. 数学専攻として、私は数学の操作などを理解できますが、ポインターは混乱していませんが、変数のアドレスなどを処理する必要なしにそれを行う方法があるように思えます.

4

2 に答える 2

5

実行すると、コンパイルされ、動作します。参照: http://ideone.com/RHWwI

したがって、それはあなたがそれをコンパイルしている方法でなければなりません。あなたのコンパイラエラーは何ですか?

于 2011-10-21T23:31:07.957 に答える
2

さて、オペレーターを完全に理解&したので*、残りは非常に簡単です。

あなたが持っているとしましょう:

int q;
int *m;
m = &q;

次に、次のように言います。

int *m2;
m2 = m;

m2には と同じ値が含まれます。mつまり、アドレスは になりますq。したがって、*mand*m2は同じ値 ( の値q)を返します (それが rightの逆演算子であること理解できますか? したがって、 and (後者の場合、適用するには へのポインターである必要があります。))*&*(&q) = q&(*m) = mm*

では、これは関数でどのように機能するのでしょうか? 単純!関数に引数を渡すときは、値で渡します。ポインターで渡す場合、実際には変数のポインターである値で渡します。

それでは、関数呼び出しを詳しく調べてみましょう。

reverse_number(in_orig, &out_orig);

あなたのin_valandout_valの名前を主にin_origandに変更したout_origので、 のそれらと混同されませんreverse_number

今、&out_origのアドレスですout_origout_val引数として渡されると、これはの引数にコピーされますreverse_number。これは、次のように記述します。

int *out_val = &out_orig;

さて、あなたの に上記の行があれば、main書くだけ*out_val = something;で が変わるでしょうout_orig? さて、あなたはout_originのアドレスを持っているので、 が またはに設定されているかどうかout_val誰が気にしますか?*out_valmainreverse_number

ご覧のように?ポインターがある場合は、それを別の変数にコピーするか、関数の引数として渡すか (基本的には同じことです) にかかわらず、それをコピーするだけで、それが指している同じ変数にアクセスできます。結局、すべてのコピーの値は同じです: address of out_orig. 関数または でアクセスしたい場合はmain、それほど重要ではありません。

編集*ポインタ定義で

**ポインタの定義にも使用できます。これは、アドレスの値を取得する演算子としての以前の使用法とは関係ありません。

これは単なる定義であるため、学習する必要があります。

型の値がある場合type(たとえばint)、その変数のアドレス ( を使用operator &) は型type *(この例では ) を持ちint *ます。ポインターはそのアドレスを取るため、ポインターの型は ですtype *

反対に、ポインターに型type *(たとえばint *) がある場合、ポインターが指す ( を使用して) 値を取得すると、operator *type(この例ではint) があります。

要約すると、次のように言えます。

operator &, adds one * to the type of the variable
operator *, removes one * from the type of the expression

それでは、いくつかの例を見てみましょう:

int x;
x has type int
&x has type int *

float *y;
y has type float *
&y has type float **
*y has type float

struct Data ***d;
d has type struct Data ***
&d has type struct Data ****
*d has type struct Data **
*(*d) has type struct Data *
*(*(*d)) has type struct Data

お気づきの方もいらっしゃると思いますが、 variableの型に&1 を追加しますが、 expressionの型からは 1 を削除します。何故ですか?変数のアドレスを与えるからです。もちろん、アドレスを持っているものは他にないからです。たとえば、(おそらく)メモリ内にアドレスがありません。アドレスがある場合は、一時的で役に立たないだけです。***&a+b

operator *ただし、アドレスでは機能します。どのようにアドレスを計算しても、それでoperator *機能します。例:

*(0x12345678) -> Note that even if the compiler let's you do this,
                 your program will most likely crash

*d -> like we saw before

*(d+4) -> This is the same as writing d[4]
          And now you know why arrays and pointers are treated as one

動的 2 次元配列の場合:

*(*(d+4)+6) -> This is the same as writing d[4][6]
于 2011-10-21T23:56:58.993 に答える