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[0] 给出了一些未知值,可能是地址,而googly 部分是&filled[0],它给出了值10。我无法获得逻辑。以下是我得到的输出

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

2 回答 2

3

格式说明符%uinprintf需要类型为 的参数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]

str组成字节的确切顺序i取决于架构。

现在,您的代码...

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.

正在发生的事情是程序将 fill[0] 的放入堆栈以供 printf 使用。格式掩码中的第一个 %u 消耗str组件,第二个消耗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 回答