C 通过在堆上分配和堆栈上分配创建的指针之间的差异

C 通过在堆上分配和堆栈上分配创建的指针之间的差异,c,pointers,C,Pointers,对于这个例子,我们有一个指向指针列表的指针 // Allocating on Stack typedef char *list[10]; char **pointer; pointer = (list) {NULL}; // Allocating on Heap char **pointer = calloc(10,sizeof(char *)); 我写上述代码的方式正确吗 还有,如果有人能解释两种情况下的字符**指针行为是否有差异,是否有差异 是,代码是有效的C11 // Alloc

对于这个例子,我们有一个指向指针列表的指针

// Allocating on Stack
typedef char *list[10];
char **pointer;
pointer = (list) {NULL};

// Allocating on Heap
char **pointer = calloc(10,sizeof(char *)); 
我写上述代码的方式正确吗

还有,如果有人能解释两种情况下的字符**指针行为是否有差异,是否有差异


是,代码是有效的C11

  // Allocating on Stack
  typedef char *list[10];
  char **pointer1;
  pointer1 = (list) {NULL};

  // Allocating on Heap
  char **pointer2 = calloc(10,sizeof(char *));
指针1[0],指针1[1]。。。指针1[9]:第一个元素被初始化为NULL,其余元素被初始化为一个零位模式-这可能是等效的

指针2[0Marc B],指针2[1]。。。指针2[9]内容设置为零。如果pointer2不为NULL,则calloc就是这样做的

指针1[0]和指针2[0]等都不指向任何字符


还要注意数据的寿命。指针1上的数据只有在作用域丢失(如函数返回)之前才有效,而指针2上的数据在释放之前一直有效。

根据复合文字的实例化位置,它可能具有静态或自动存储持续时间。假设以下代码去掉了typedef,使事情更清楚一些:

#include <stdio.h>

char **pointer = (char *[10]){NULL};

int main( void )
{
   ...
}
变量指针具有静态存储持续时间,但它指向的字符指针的10元素数组具有自动存储持续时间;阵列的存储在main入口留出,并在main出口时释放。具有自动存储持续时间的对象通常从堆栈中分配,但请记住,堆栈是一个实现细节,不是由C语言定义的

下一个变化:

#include <stdio.h>

int main( void )
{
  char **pointer = (char *[10]){NULL};
  ...  
}
与堆栈一样,堆也是一个实现细节,不是由C语言定义的


阵列的存储由malloc调用留出并保留,直到有相应的空闲调用为止。根据上述规则,指针变量的存储仍然是静态的或自动的。创建具有分配的存储持续时间的对象的唯一方法是使用malloc、calloc或realloc之一

函数返回后,calloc的内存将保留,但它可能会丢失,例如内存泄漏。当函数返回时,堆栈版本将自动消失。指针在这两种情况下的行为相同。指针指向的东西可能会有不同的行为。怀疑一些反对票是由于对C11不熟悉,然后假设代码格式不正确。@chux I的印象是,指针指向的任何东西都是临时的,只有在;但是根据你的答案和地址Sanitizer和MemorySanitizer以及Valgrind,我错了,所以我将删除我的注释。前3行代码是否会在堆栈上分配一个数组,然后给我一个指向它的指针?还是在堆栈上进行分配?ThanksTack和Heap不是C规范的一部分。它取决于机器/编译器,两者都未说明。第一个只声明一个类型,没有代码。第二行声明一个指针。第三行将该指针指定给复合文字列表{NULL}的地址,该列表可能是在堆栈上分配的。
#include <stdio.h>

int main( void )
{
  char **pointer = (char *[10]){NULL};
  ...  
}
char **pointer = malloc( sizeof *pointer * 10 );