char x [256] vs. char*= malloc(256*sizeof(char));

fac*_*_14 13 c arrays malloc

最近有人在我使用的一段代码中向我指出

char* name = malloc(256*sizeof(char));
// more code
free(name);
Run Code Online (Sandbox Code Playgroud)

我的印象是这种设置阵列的方式与使用相同

char name[256];
Run Code Online (Sandbox Code Playgroud)

并且两种方式都需要使用free().我错了,如果是这样,有人可以用低级别的术语解释有什么区别?

Ned*_*der 28

在第一个代码中,内存在堆上动态分配.需要使用free()释放内存.它的寿命是任意的:它可以跨越功能边界等.

在第二个代码中,256个字节在堆栈上分配,并在函数返回时自动回收(如果它在所有函数之外,则在程序终止时).所以你不必(也不能)调用free()就可以了.它不会泄漏,但它也不会超出功能的终点.

根据内存要求在两者之间进行选择.

附录(Pax):

如果我可以添加这个,Ned,大多数实现通常会提供比堆栈更多的堆(至少在默认情况下).这通常不会对256字节有影响,除非你已经耗尽了堆栈或做了很多递归的东西.

此外,sizeof(char)根据标准始终为1,因此您不需要多余的乘法.即使编译器可能会优化它,它也会让代码变得丑陋IMNSHO.

结束附录(Pax).

  • 在附录(Pax)中,我认为在调用malloc时包含sizeof(type)是一种好习惯.如果类型在使用sizeof()而不是暗示时更改,则不太可能忘记更改分配的大小. (2认同)
  • @strager:另一个常见的模式是使用`char*foo = malloc(sizeof(*foo))`来降低它的可能性. (2认同)

Joh*_*itb 7

并且两种方式都需要使用free().

不,只有第一个需要免费使用.第二个是在堆栈上分配的.这使得分配速度极快.看这里:

void doit() {
    /* ... */
    /* SP += 10 * sizeof(int) */
    int a[10];
    /* ... (using a) */

} /* SP -= 10 */
Run Code Online (Sandbox Code Playgroud)

在创建它时,编译器在编译时知道它的大小,并在堆栈中为它分配正确的大小.堆栈是位于某处的大块连续内存.将东西放在堆栈中只会增加(或减少,具体取决于您的平台)stackpointer.超出范围将反过来,并释放您的数组.这将自动发生.因此创建的变量具有自动存储持续时间.

使用malloc是不同的.它会命令一些任意大的内存块(来自一个名为freestore的地方).运行时必须查找相当大的内存块.大小可以在运行时确定,因此编译器通常无法在编译时对其进行优化.因为指针可能超出范围,或者被复制,所以分配的内存与分配内存地址的指针之间没有固有的耦合,所以即使你很久以前离开了函数,内存仍然被分配.如果时间已经到了,你必须自由地调用你手动从malloc获得的地址.

C的一些"最近"形式称为C99,允许您为数组提供运行时大小.即你被允许这样做:

void doit(int n) {
    int a[n]; // allocate n * sizeof(int) size on the stack */
}
Run Code Online (Sandbox Code Playgroud)

但如果您没有理由使用它,最好避免使用该功能.一个原因是它不是故障安全的:如果没有可用的内存,任何事情都可能发生.另一个原因是C99在编译器中不是很便携.


Cha*_*tin 5

这里有第三种可能性,即数组可以在函数外部声明,但静态地,例如,

// file foo.c
char name[256];

int foo() {
    // do something here.
}
Run Code Online (Sandbox Code Playgroud)

我对另一个关于SO的问题的回答感到相当惊讶,有人觉得这在C中是不合适的; 这里甚至都没有提到,我有点困惑和惊讶(比如"这些天他们在学校里教孩子的原因是什么?").

如果使用此定义,则内存将静态分配,既不在堆上也不在堆栈中,而是在映像中的数据空间中.因此,既不必像malloc/free一样进行管理,也不必担心地址被重用,就像使用自动定义一样.

在这里回忆整个"声明"与"定义"的事情是有用的.这是一个例子

/* example.c */

char buf1[256] ;           /* declared extern, defined in data space */
static char buf2[256] ;    /* declared static, defined in data space */
char * buf3 ;              /* declared extern, defined one ptr in data space */
int example(int c) {       /* c declared here, defined on stack */
    char buf4[256] ;       /* declared here, defined on stack   */
    char * buf5 = malloc(256)]   /* pointer declared here, defined on stack */
                           /* and buf4 is address of 256 bytes alloc'd on heap */
    buf3 = malloc(256);    /* now buf3 contains address of 256 more bytes on heap */

    return 0;              /* stack unwound; buf4 and buf5 lost.      */
                           /* NOTICE buf4 memory on heap still allocated */
                           /* so this leaks 256 bytes of memory */
}
Run Code Online (Sandbox Code Playgroud)

现在在一个完整的不同文件中

/* example2.c */

extern char buf1[];             /* gets the SAME chunk of memory as from example.c */
static char buf2[256];          /* DIFFERENT 256 char buffer than example.c */
extern char * buf3 ;            /* Same pointer as from example.c */
void undoes() {
     free(buf3);                /* this will work as long as example() called first */
     return ;
}
Run Code Online (Sandbox Code Playgroud)