关于char*缓冲区和char缓冲区的内存分配[5]

关于char*缓冲区和char缓冲区的内存分配[5],c,ubuntu,memory,stack,C,Ubuntu,Memory,Stack,我想问一个关于char*buffer的内存分配问题;缓冲区=malloc(5);和字符缓冲区[5] 我的测试代码如下:] #include <stdio.h> void echo1(); void echo2(); int main() { echo1(); printf("\n"); echo2(); printf("Back to Main \n"); return 0; } void echo1() { int i;

我想问一个关于char*buffer的内存分配问题;缓冲区=malloc(5);和字符缓冲区[5]

我的测试代码如下:]

#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); 
}
#包括
void-echo1();
void-echo2();
int main(){
echo1();
printf(“\n”);
echo2();
printf(“返回主\n”);
返回0;
}
void echo1(){
int i;
无符号长地址;
字符*缓冲区;
printf(“[Echo1]缓冲区:%p\n”,缓冲区);
printf(“[Echo1]&缓冲区:%p\n”,&缓冲区);
缓冲区=malloc(5);
printf(“[Echo1]&缓冲区:%p\n”,&缓冲区);
printf(“[Echo1]缓冲区:%p\n”,缓冲区);
对于(i=0;i<5;i++){
缓冲区[i]=“A”;
}
printf(“[Echo1]Buffer[]:%s\n”,Buffer);
addr=&buffer;
printf(“[Echo1]*缓冲区:%p\n”,*缓冲区);
printf(“[Echo1]地址:%p\n”,地址);
printf(“[Echo1]&地址:%p\n”,&addr);
}
void echo2(){
int i;
无符号长地址;
字符缓冲区[5];
printf(“[Echo2]缓冲区:%p\n”,缓冲区);
printf(“[Echo2]&缓冲区:%p\n”,&缓冲区);
对于(i=0;i<5;i++){
缓冲区[i]=“A”;
}
printf(“[Echo2]Buffer[]:%s\n”,Buffer);
addr=&buffer;
printf(“[Echo2]*缓冲区:%p\n”,*缓冲区);
printf(“[Echo2]地址:%p\n”,地址);
printf(“[Echo2]&地址:%p\n”,&addr);
}
我在ubuntu上通过键入gcc test.c-o test-m32编译了它(我使用的是64位机器)。下图显示了结果。

我想我理解了echo1()的情况(除了为什么addr位于缓冲区之上),并制作了一个图来显示内存中发生了什么。

但我不知道echo2()案发生了什么

因此,我想问以下问题:

  • 在echo1()中,我在buffer之前声明了addr,为什么addr被放在堆栈的buffer之上?(既然堆栈向上移动,程序不应该先推addr,然后再推缓冲区吗?)
  • 在echo2()中,为什么buffer和&buffer给出相同的值?这不意味着缓冲区指向它自己吗
  • 在echo2()中,addr的地址和addr的内容(缓冲区地址)由12个字节分隔,其中存储了什么
  • 有人能给我一个数字来帮助我理解在ehco2()中发生了什么吗
  • 非常感谢

    为什么相同

    堆栈上数组的地址与其第一个元素的地址相同。不同之处在于结果指针的大小不同,因此它们会递增

    中间是什么

    指针的地址是堆栈地址,而
    malloc()
    返回并存储在指针中的地址来自堆

    注意:您的代码还显示了许多未定义行为的来源,例如

    • 使用
      %p”
      说明符打印
      *缓冲区
    • 打印未初始化的指针
    • 打印
      未初始化的无符号长地址
      并使用
      “%p”
      说明符,这两个说明符都调用未定义的行为
    • 使用
      “%s”
      说明符打印非
      null
      终止的数组
    因此,您不能期望在
    echo2()
    和整个程序中出现给定的行为

    为什么相同

    堆栈上数组的地址与其第一个元素的地址相同。不同之处在于结果指针的大小不同,因此它们会递增

    中间是什么

    指针的地址是堆栈地址,而
    malloc()
    返回并存储在指针中的地址来自堆

    注意:您的代码还显示了许多未定义行为的来源,例如

    • 使用
      %p”
      说明符打印
      *缓冲区
    • 打印未初始化的指针
    • 打印
      未初始化的无符号长地址
      并使用
      “%p”
      说明符,这两个说明符都调用未定义的行为
    • 使用
      “%s”
      说明符打印非
      null
      终止的数组
    因此,您不能期望在
    echo2()
    和整个程序中出现给定的行为

    有人能给我一个数字来帮助我理解发生了什么吗 ehco2()

    对于整个问题,最好的答案是使用gcc的-O0标志生成未优化的代码,并在调试器中运行它,或者还使用-s来查看与它生成的代码相对应的程序集

  • 在echo1()中,我在buffer之前声明了addr,为什么addr被放在堆栈的buffer之上?(既然堆栈向上移动,那么 程序首先推送addr,然后在其上推送缓冲区?)
  • 但直到将一个值分配给缓冲区之后,您才将一个值分配给addr,因此编译器直到稍后才需要为它分配内存

    关于其他几点,请参见iharob的好答案

    有人能给我一个数字来帮助我理解发生了什么吗 ehco2()

    对于整个问题,最好的答案是使用gcc的-O0标志生成未优化的代码,并在调试器中运行它,或者还使用-s来查看与它生成的代码相对应的程序集

  • 在echo1()中,我在buffer之前声明了addr,为什么addr被放在堆栈的buffer之上?(既然堆栈向上移动,那么 程序首先推送addr,然后在其上推送缓冲区?)
  • 但直到将一个值分配给缓冲区之后,您才将一个值分配给addr,因此编译器直到稍后才需要为它分配内存

    关于其他几点,请参见iharob的好答案

    在echo1()中,我在buffer之前声明了addr,为什么addr被放在堆栈的buffer之上

    因为编译器不必按照声明的顺序将自动变量放入堆栈,而且显然选择不这样做。(事实上,它根本不需要把它们放在堆栈上——它是c