你的代码
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] 不是一个简单的数据类型。