数组声明表示法是 C 语言中 malloc 的简写吗?

Is array declaration notation a shorthand for malloc in C?

提问人:Connor 提问时间:3/9/2023 更新时间:3/11/2023 访问量:93

问:

从本教程网站

要在 C 中声明一个数组,程序员指定 元素和数组所需的元素数如下 -

type arrayName [ arraySize ];

似乎此语法声明了数组并为其提供了内存空间,但它不会初始化任何值。

这似乎类似于命令。上面的符号是 的简写吗?mallocmalloc

数组 C 初始化 malloc 声明

评论

1赞 Karthick 3/9/2023
malloc在堆中分配内存,需要显式释放。
3赞 Lundin 3/9/2023
Tutorialspoint 是一个臭名昭著的糟糕网站。你不应该从不懂 C 编程的人那里学习 C 编程。
0赞 Connor 3/9/2023
@Lundin 很好的建议!我应该去哪里寻找?
2赞 Lundin 3/9/2023
stackoverflow.com :)
1赞 Lundin 3/9/2023
@Connor 对于那种“查找”的问题,人或 cppreference.com 的 C 部分

答:

3赞 0___________ 3/9/2023 #1

这似乎类似于 malloc 命令。上面的符号是 Malloc 的简写?

不,不是。

根据存储持续时间的不同,未初始化的对象将是:

  1. 具有静态存储持续时间的 Zeroed
  2. 如果它们具有自动存储持续时间,则未初始化
type array_static_storage_duration [ arraySize ];

void foo(void)
{
     type array_automatic_storage_duration [ arraySize ];
     static type array_static_storage_duration1 [ arraySize ];
    
}

自动存储持续时间对象将在您退出已定义的范围时停止存在。

使用分配的对象具有分配的存储持续时间,其生存期与程序相同(除非您使用它们)mallocfree

从 C 标准:

标识符使用 external 或 internal 声明的对象 联动,或与存储类说明符 static 具有 static storage 期间。它的生命周期是程序的整个执行及其 在程序启动之前,存储的值仅初始化一次。

一个对象,其标识符声明时没有链接,也没有 存储类说明符 static 具有自动存储持续时间。

5 对于 这样一个没有可变长度数组类型的对象,其 生存期从进入与其关联的块开始延伸 直到该块的执行以任何方式结束。(进入一个封闭的 阻止或调用函数会暂停但不会结束 当前块。如果以递归方式输入块,则新的 每次都会创建对象的实例。初始值 对象是不确定的。如果为 对象,则每次在 区块的执行;否则,该值将变为不确定 每次达到声明时。

6 对于这样的对象 具有可变长度数组类型,其生存期从 声明对象,直到程序执行离开 27) 如果范围是递归输入的,则 每次都会创建对象的新实例。的初始值 对象是不确定的。

1赞 August Karlstrom 3/9/2023 #2

否,函数 malloc 在运行时从可用存储(或堆)分配内存。这个内存可以像数组一样访问,但它被分配给一个指针。这种动态分配的“数组”通常用于我们事先不知道它需要多大的情况。内存也需要通过函数free释放。

评论

0赞 Connor 3/9/2023
当我们将数组作为返回值传递时,我们是否也使用?如果是这样,数组声明表示法的意义何在?它似乎没有多大用处。malloc
1赞 August Karlstrom 3/9/2023
您可以使用 malloc 的结果作为返回值,但写入调用方传递给函数的数组更为惯用。非动态数组具有更好的性能,因为它们要么是静态分配的,要么是堆栈分配的。一些编程语言(如果我没记错的话,比如 Java)在后台只使用堆分配的数组。
0赞 Connor 3/9/2023
伟大!我刚刚在麻省理工学院的一次讲座中偶然发现了与此类似的描述!那么,我是否应该将堆栈引用数组传递到内部函数中以使过程更快?
1赞 August Karlstrom 3/10/2023
@Connor 是的,这样效率更高。传递数组的长度也是一个好主意,以便函数知道它的结束位置。
3赞 Lundin 3/9/2023 #3

与此相关的是存储持续时间的 C 概念,它主要说明变量保证保持有效的时间,以及变量是否/如何默认初始化,以及在什么条件下它持有不确定的值(本质上是“垃圾值”)。

  • 静态存储时长的对象保证为零初始化。在任何函数外部声明和/或具有静态存储持续时间的所有对象。因此,如果示例中的数组在任何函数外部声明,则保证它是零初始化的。static

  • 具有自动存储持续时间的对象不会初始化,除非程序员明确这样做。这些都是在局部作用域声明的变量,我们称之为局部变量。还有函数的参数。如果示例中的数组是在函数中声明的,则它具有自动存储持续时间,并且它包含的值是不确定的。

  • 具有分配存储持续时间的对象是由函数系列显式创建的对象。是否初始化它们取决于使用的函数:不初始化值,但使它们不确定,将所有值初始化为零。mallocmalloccalloc

因此,碰巧的是,具有自动存储持续时间的变量与从 返回的具有分配存储持续时间的数据具有相同的初始化规则。但这就是这两种变量类型的共同点。malloc

C 语言并不规定某些内容在内存中的存储位置。然而,在实践中,C语言中的堆分配可能只在函数明确表示会发生时才会发生。除了 family 之外,还有一些非标准的 ,比如 和 它们明确记录了它们在内部使用堆分配。mallocstrdupgetline

话虽如此,例如 stdio.h 的某些实现可能会在内部使用堆分配 - 就 C 标准而言,这很好。如果他们不记录下来,他们也会在内部进行清理。free()

1赞 John Bode 3/11/2023 #4

上面的符号是 malloc 的简写吗?

不。将数组声明为

T a[N];

你在内存中得到的内容看起来像这样:

   +---+
a: |   | a[0]
   +---+ 
   |   | a[1]
   +---+ 
   |   | a[2]
   +---+
    ...

除了数组元素本身之外,没有其他对象。如果在本地声明给函数,例如a

void foo( void )
{
  T a[N];
  ...
}

数组的内存(通常)将与任何其他局部变量来自同一存储区。当函数退出时,该内存也将被释放。

当您将内存分配为

T *a = malloc( sizeof *a * N );

您在内存中得到的内容如下所示:

   +---+         +---+
a: |   | ------> |   | a[0]
   +---+         +---+
                 |   | a[1]
                 +---+
                 |   | a[2]
                 +---+
                  ...

指针变量的分配与任何普通变量一样,一旦函数退出,它就会被销毁,但为数组元素分配的内存不是 - 该内存将保持分配状态,直到您显式调用 ,因此您需要将该指针返回到任何调用函数,或者在退出当前函数之前释放内存。afree