C中的动态数组不使用malloc吗?

10 浏览
0 Comments

C中的动态数组不使用malloc吗?

我一直想知道如何逃脱这个问题:

int main(int argc, char **argv) {
    printf("%p %s %d\n", &argv[1], argv[1], strlen(argv[1]));
    char copy[strlen(argv[1]) + 1];
    strcpy(copy, argv[1]);
    printf("%p %s %d\n", ©, copy, strlen(copy));
    return 0;
}

字符数组copy仍然被分配,并且程序正常运行,打印出原始值和拷贝值。而且Valgrind没有抱怨任何问题。

我以为在C语言中没有办法使用动态数组而不使用malloc。我错了吗?

0
0 Comments

在C语言中,即使在出现“可变长数组”(Variable Length Arrays)之前,由于gcc和C99的存在,也有一种动态分配堆栈(自动)内存的方法:alloca()。根据BSD man page中对于alloca的介绍,它在AT&T Unix的Version 32V中被引入(1979年)。所以它已经存在了相当长的时间。

然而,当分配可能较大的内存时,alloca被认为是有问题的。但是,感谢你的回答,但这并不完全正确。你个人试过了吗?程序通常可以使用的堆栈空间远远超过“几百个字节”。当然,我们始终需要注意机器的限制,但假设alloca()比sbrk()更受限制,这是不合理的。

所以为什么alloca被认为是有问题的呢?主要原因是它在堆栈上分配内存,而不是在堆上。由于堆栈空间是有限的,如果分配的内存较大,可能导致堆栈溢出(stack overflow)。而且,由于alloca分配的内存是在函数调用时分配的,当函数返回时,这些内存就会被释放,可能导致悬空指针(dangling pointers)的问题。

那有没有解决alloca的问题的方法呢?解决方法之一是使用malloc来替代alloca。malloc分配的内存是在堆上,而不是在堆栈上,因此可以避免堆栈溢出的问题。另一种解决方法是使用可变长数组(Variable Length Arrays,VLA)。VLA是C99标准中引入的特性,它允许在函数内部动态地分配数组,而不需要使用alloca。使用VLA可以避免悬空指针的问题,并且更加安全和可靠。

尽管alloca在一些情况下可能存在问题,但在一些小规模的内存分配中仍然可以使用。然而,为了避免潜在的问题和不确定性,更好的选择是使用malloc或VLA来动态分配内存。

0
0 Comments

在C语言中,动态数组是一种常见的数据结构,允许在运行时根据需要改变数组的大小。然而,标准的C语言(C90)并不支持动态数组,这给开发者带来了一定的困扰。

幸运的是,C99引入了一种新的特性,即可变长度自动数组(Variable-length automatic arrays)。这种特性允许在声明数组时使用非常量表达式作为数组的长度。在C99标准中,这样声明的数组会在声明时分配存储空间,并在当前作用域结束时释放。

然而,C99并不是所有编译器都完全支持的,因此GCC提供了对C90和C++的扩展,允许在这些版本中使用可变长度自动数组。这样,即使在旧版本的编译器中,开发者也能够利用可变长度自动数组的便利。

下面是一个使用可变长度自动数组的示例代码:

#include 
void printArray(int size, int array[size]) {
  for (int i = 0; i < size; i++) {
    printf("%d ", array[i]);
  }
  printf("\n");
}
int main() {
  int n;
  printf("Enter the size of the array: ");
  scanf("%d", &n);
  int array[n]; // 可变长度自动数组的声明
  printf("Enter %d elements: ", n);
  for (int i = 0; i < n; i++) {
    scanf("%d", &array[i]);
  }
  printf("The array is: ");
  printArray(n, array);
  return 0;
}

在上面的示例代码中,我们首先从用户那里获取数组的大小n,然后声明一个可变长度自动数组array来存储用户输入的元素。最后,我们调用printArray函数来打印数组的内容。

通过使用可变长度自动数组,开发者可以方便地根据需要动态分配和使用数组。这种特性不仅提高了代码的灵活性,还减少了手动内存管理的工作量。

总结起来,C语言中没有原生支持动态数组的特性,但通过可变长度自动数组的使用,我们可以在C99标准及其扩展的编译器中实现类似的功能。通过动态数组,开发者可以更加灵活地处理数据,并减少手动内存管理的复杂性。

0
0 Comments

动态数组在C语言中没有使用malloc函数的原因是因为变长数组最早是作为GCC的扩展功能出现的,但后来也被C99标准所采纳。变长数组仍然是在堆栈上分配的,因此将它们设定为“巨大”被认为是不好的风格(而且将来可能会出问题)。

变长数组在C语言中没有使用malloc函数的解决方法是避免使用变长数组,因为它们容易导致堆栈溢出的问题。尽管可以通过了解目标平台的堆栈限制并加以考虑来减少风险,但是在实际中,代码往往会超出目标平台的范围。此外,即使有一些静态检查器(如Coverity)可以计算程序的总堆栈消耗的上限,但在存在变长数组等情况下可能无法准确计算。因此,最好避免使用这种功能,尽管每个规则都有例外。

作者同意上述观点,他经常使用递归来实现简单和方便的解决方案,但是对于大型不确定的堆栈模式,需要额外的考虑。

0