0
struct abc filled[]={{"aa",10},{"bb",20}};    
   printf("[%u,%u]\n",filled,&filled);
   printf("[%u,%u]\n",filled[0],&filled[0]);

   printf("[%u,%u]\n",filled+1,&filled+1);
   printf("[%u,%u]\n",filled[1],&filled[1]);

塗りつぶされた配列はメモリ内でどのように配置されますか? 配列の名前であるfilledは、配列のベースアドレスを返します...同様に&filledです。しかし、filled[0] は未知の値を与えます。アドレスである可能性があり、グーグル部分は &filled[0] であり、値 10 を与えます。ロジックを取得できません。以下は私が得ている出力です

[2293552,2293552]    
[4206592,10]    
[2293560,2293568]    
[4206595,20]    
4

2 に答える 2

3

%uinの書式指定子にprintfは type の引数が必要unsigned intです。構造体型のポインターとオブジェクトなど、まったく関係のない型の引数を指定しています。このため、コードは未定義の動作を示します。コードが壊れており、その出力は完全に無意味です。それを分析したり説明しようとしてもあまり意味がありません。(説明は確かに存在しますが、主要な質問とは何の関係もありません。)

配列がメモリ内でどのように配置されるかについては... StackOverflowは、まさにこの質問に対する繰り返しの回答でいっぱいです。検索してみてください。

于 2013-10-28T05:05:48.710 に答える
2

あなたのコード

struct abc filled[]={{"aa",10},{"bb",20}};    
printf("[%u,%u]\n",filled,&filled);
printf("[%u,%u]\n",filled[0],&filled[0]);

これについてさらに議論する前に、「構造体」がどのようなものかを理解する必要があります。あなたは定義を提供しなかったので、私はそれが次のようなものであると仮定します

struct abc {
    const char* str;
    int i;
};

これらfilledのオブジェクトの配列も同様です。

filled[] = {
    struct abc { str = "aa", i = 10 },
    struct abc { str = "bb", i = 20 }
};

filled[0]スペース内の最初の構造体 abc を参照します。

{ str = "aa", i = 10 }

メモリ内の 32 ビット ビルドでは、[...] がバイトを表すように配置されます。

[ptr][ptr][ptr][ptr][i][i][i][i]

64 ビット システムでは、これらは次のように配置されます。

[ptr][ptr][ptr][ptr][ptr][ptr][ptr][ptr][i][i][i][i]

構成するバイトの正確な順序は、アーキテクチャによって異なりますstri

さて、あなたのコード...

struct abc filled[]={{"aa",10},{"bb",20}};    
printf("[%u,%u]\n",filled,&filled);
printf("[%u,%u]\n",filled[0],&filled[0]);

printf には制限があります。基礎となる関数は、実際に引数を見ることはできません。スタック上のデータを取得するだけで、出力形式をガイドとして使用します。

最終的にひどく間違っているのは、構造体を printf 引数として渡していることです。

printf("[%u,%u]", filled[0], &filled[0]);

filled[0]に解決されstruct abcます。

何が起こっているかというと、プログラムは、printf が使用できるように、filled[0]の値をスタックに入れているということです。フォーマット マスクの最初の %u はstrコンポーネントを消費し、2 番目はi.

これが完全なプログラムの場合:

#include <stdio.h>

struct abc {
    const char* str;
    int i;
};

int main() {
    struct abc filled[] = { { "aa", 16 }, { "bb", 20 } };
    printf("filled = %p\n", filled);
    printf("&filled = %p\n", &filled);
    printf("filled[0] = %p\n", filled[0]);
    printf("&filled[0] = %p\n", &filled[0]);
    printf("filled[0].str = %p\n", filled[0].str);
    printf("filled[0].i = %d\n", filled[0].i);
    return 0;
}

出力は次のとおりです。

filled = 0xbfba5cb0
&filled = 0xbfba5cb0
filled[0] = 0x80485b0     <--+
&filled[0] = 0xbfba5cb0      | filled[0] actually printed the .str value
filled[0].str = 0x80485b0 <--+
filled[0].i = 16

Visual Studio を使用して、または -Wall を使用せずにコンパイルしているため、不足しているのは次のコンパイラ警告です。

prog.c: In function ‘main’:
prog.c:12:5: warning: format ‘%p’ expects argument of type ‘void *’, but argument 2 has type ‘struct abc’ [-Wformat=]
     printf("filled[0] = %p\n", filled[0]);

あなたがするとき

printf("[%u, %u]\n", filled[0], &filled[0]);

プログラムは次のことを行います。

push stack (const char*) "[%u, %u]\n"   // in 32-bit, 4-bytes of pointer.
push stack (struct abc) filled[0]       // pushes the entire of filled[0], str and i, 8 bytes.
push stack (struct abc*) &filled[0]     // pushes another 4 bytes.

結果のスタックは次のようになります

ここに画像の説明を入力

スタック上のデータを読み取るための正しい形式を指定しなかったため、printf は「&filled[0]」の値を使用しません。代わりに使用した場合

printf("filled[0].str=%p, filled[0].i=%u, &filled[0]=%p\n", filled[0], &filled[0]);

そうすれば、より意味のあるデータが得られますが、データのレイアウトとスタックについて多くの仮定が行われるため、結果を得るには危険な方法です。

基本的に、あなたの問題はあなたがこれをしていることです:

printf("%u", 塗りつぶし[0]);

ここで、filled[0] は単純なデータ型ではありません。

于 2013-10-28T05:49:06.913 に答える