我想问一个关于char *缓冲区、buffer =malloc(5)和char buffer5的内存分配问题。
我的测试代码如下:]
#include <stdio.h>
void echo1();
void echo2();
int main() {
echo1();
printf("\n");
echo2();
printf("Back to Main \n");
return 0;
}
void echo1() {
int i;
unsigned long addr;
char *buffer;
printf("[Echo1] Buffer : %p \n", buffer);
printf("[Echo1] &Buffer : %p \n", &buffer);
buffer = malloc(5);
printf("[Echo1] &Buffer : %p \n", &buffer);
printf("[Echo1] Buffer : %p \n", buffer);
for (i = 0; i < 5; i++) {
buffer[i] = 'A';
}
printf("[Echo1] Buffer[] : %s \n", buffer);
addr = &buffer;
printf("[Echo1] *Buffer : %p \n", *buffer);
printf("[Echo1] addr : %p \n", addr);
printf("[Echo1] &addr : %p \n", &addr);
}
void echo2() {
int i;
unsigned long addr;
char buffer[5];
printf("[Echo2] Buffer : %p \n", buffer);
printf("[Echo2] &Buffer : %p \n", &buffer);
for (i = 0; i < 5; i++) {
buffer[i] = 'A';
}
printf("[Echo2] Buffer[] : %s \n", buffer);
addr = &buffer;
printf("[Echo2] *Buffer : %p \n", *buffer);
printf("[Echo2] addr : %p \n", addr);
printf("[Echo2] &addr : %p \n", &addr);
}我通过输入gcc test.c -o测试-m32 (我使用64台机器)在ubuntu上编译了它。下图显示了结果。

我想我理解echo1()的情况(除了为什么addr在缓冲区之上),并做了一个数字来显示内存中发生了什么。

但我不知道在echo2()情况下发生了什么。
所以我想问以下几个问题:
非常感谢。
发布于 2016-01-28 01:41:05
为什么是一样的?
堆栈上的数组的地址与其第一个元素的地址相同。差异在于增加结果指针,因为它们有不同的大小。
中间是什么?
指针的地址是堆栈地址,而malloc()返回并存储在指针中的地址来自堆。
注意:您的代码还显示了许多未定义行为的来源,例如
*Buffer说明符打印"%p"。unsigned long addr和使用"%p"说明符打印,两者都调用未定义的行为。null说明符的非"%s"终止数组。因此,您不能期望在echo2()和整个程序中出现给定的行为。
发布于 2016-01-28 02:09:34
有人能做一个数字来帮助我理解ehco2()中发生的事情吗?
解决这个问题的最佳方法是使用gcc的-O0标志来生成未优化的代码,或者在调试器中运行它,或者使用-S来检查与其生成的代码对应的程序集。
但是,直到将一个值分配给缓冲区之后,才为addr分配一个值,所以编译器直到稍后才会为其分配内存。
其他几点见艾哈洛布的好答案。
发布于 2016-01-28 02:42:38
在echo1()中,我在缓冲区之前声明了addr,为什么addr放在堆栈缓冲区的上方?
因为编译器不需要按照声明的顺序将自动变量放到堆栈上,而且显然,它选择不这样做。(实际上,它根本不需要将它们放到堆栈中--如果它们适合于寄存器,它可以将它们放入寄存器中。)
在echo2()中,为什么缓冲区和&缓冲区提供相同的值?这不意味着缓冲区是指向自己的吗?
这意味着buffer是数组,在大多数上下文中,表达式buffer计算为指向buffer的第一个元素的指针,即计算为&buffer[0],而'&buffer`‘计算为指向数组的指针,但数组的地址与数组的第一个元素的地址相同。
然而,buffer和&buffer有不同的数据类型(“指向char的指针”与“指向5char的数组的指针”)。
在echo2()中,addr的地址和addr的内容(缓冲区的地址)被分隔为12个字节,其中存储了什么?
无论编译器决定将其放在堆栈框架中。堆栈帧的布局不受C(或C++)程序员的直接控制。也许编译器决定将数组后面的地址设置为4字节边界,而不是将第一个元素放在4字节边界上。也许,由于您没有在打开优化的情况下进行编译,所以它没有将i放入寄存器中,而是将其放在堆栈中。
C不是一种编程语言,它指定自动变量与堆栈上位置之间的严格映射;编译器可以自由地将变量放在它选择的任何位置(如我前面所说,如果可能的话,可以将变量放入寄存器中)。
https://stackoverflow.com/questions/35051415
复制相似问题