2

関数fの奇妙な行を見てください。

typedef char thing[1];

void f(thing t){
    thing *p;

    /* Strange line. Changing t to  &t is wrong. 
       C++ require a (thing *) cast.
     */
    p = t;

    *(*p) = 'C';
}

int main(int argc, char* argv[])
{
    thing g;
    thing *h;

    /* Works as expected. */
    h = &g;  

    g[0] = 'A';
    *(*h) = 'B';
    f(g);

    /* g[0] is now  'C' */

    return 0;
}

fを に変更

void f(thing t){
    char **p; 
    p = &t; /* note the & */
    *(*p) = 'C';
}

も機能します。

p=&tではなく、正しい指示であると期待していましp=tた。結局tは であり、thing&tなければなりませんthing*

その奇妙な行で何が起こったのですか?

4

4 に答える 4

4

配列をパラメーターとして渡すと、ポインターに減衰します。したがってf、実際にはchar *.
次に、それを 2 回逆参照しようとします。別のポインターへのポインターとして扱いますchar。これはどうやってもうまくいきません。
キャストしないと、C++ (および警告を有効にする場合は C) が何か問題があることを通知します。キャストすると、実際にはコンパイラにエラーを無視するように指示します。しかし、それはまだ間違っています。

于 2012-06-24T19:22:49.417 に答える
2

いいえ、でtはありませんthing

正式な引数として、配列型 (配列への参照ではない) は最初の要素へのポインターに崩壊し、関数型は関数へのポインターに崩壊します。

したがって、関数では、配列のアドレスではなく、ポインターへのポインターを生成するポインター変数のアドレスを取得しています。

于 2012-06-24T19:29:59.577 に答える
1

代替ソリューション:

配列を参照渡しすることで、配列からポインターへの減衰を防ぐことができます。これはあなたが望むように動作するはずです:

void f(thing& t){
    thing *p;

    p=&t;

    *(*p)='C';
}
于 2012-06-24T19:35:33.243 に答える
0

文字通り、この行を 1 行ずつ見て、理解できないことが明確になることを願っています。

void f(thing t){

ここでは、配列を参照渡ししていないため、配列の最初の要素 ( tis a char *) へのポインターに崩壊します。

thing *p;

ここで、pは 1 文字の配列へのポインタなので、char (*p) [1].

p=t;

ここで、文字へのポインターを配列へのポインターに割り当てようとしています。タイプが単に一致しません (私は のようなものを取得しますinvalid conversion from char * to char (*)[1])。

*(*p)='C';

これは単に逆参照pして実際の配列を取得し、逆参照される最初の要素へのポインターに減衰して、最初の要素を効果的に提供します。


主に:

thing g;
thing *h

これで、関数に渡されることを扱っていません。gは でchar [1]ありhchar (*)[1]です。

h=&g;  

hは配列へのポインタ、gは配列です。これは完全に理にかなっています。

g[0]='A';

g配列です。これは正常です。

*(*h)='B';

ここでは、 と同じことを行っていますf()


変更された関数では:
まず最初に、最初の要素 ( )tへのポインターであることを覚えておいてください。char *

char * *p; 

pへのポインタchar *です。

p=&t; /* note the & */

char *へのポインターにa のアドレスを割り当てていますchar *。完全に正常です。

*(*p)='C';

*p( )pを取得するための逆参照。別の間接参照により、配列の最初の要素である が指しているものが得られます。char *tt

これで混乱が解消されることを願っています。

于 2012-06-24T19:47:28.770 に答える