将指针数组设置为NULL的标准方法是什么?

时间:2019-11-22 10:59:38

标签: c arrays

请考虑这样的堆分配的指针数组:

Thing** array = malloc(sizeof(Thing*) * array_length);

如何将其所有成员设置为NULL

我当然可以这样做:

for (int i = 0; i < array_length; i++) {
    array[i] = NULL;
}

但是我想知道是否有标准功能。

SO主要提到memset,但是我不确定在这个用例上它是否可以保证在所有平台上都能工作,因为据我所知,它是逐字节而不是逐元素地遍历数组。

通常,将任何类型的T数组(可以是任意大小)中的所有值设置为某个特定值的标准方法是什么?

4 个答案:

答案 0 :(得分:5)

您的方法很好

我想不出什么比您已经在做的更好的方法了。简短明了。绝对没有错,我什至不会考虑其他事情。

如果要保存几行,可以使用以下其中一项:

  • for (size_t i = 0; i < array_length; i++) // No braces
        array[i] = NULL;
    
  • for (size_t i = 0; i < array_length; i++) array[i] = NULL; // Single

  • for (size_t i = 0; i < array_length; i++) { array[i] = NULL; } // With braces

但是我想指出,有些人对此有强烈的意见。对于单条语句循环,我经常跳过花括号。如果使用这些技术中的任何一种,请做好投诉准备。

不安全的替代方案

您可以使用memset,它在大多数情况下都可以使用。但是,C标准不要求空指针全为零。诚然,因此而导致失败的风险微乎其微,但是为什么要在收益接近零时冒险呢?如果您问我,循环会更清晰,因为您的目标是将指针设置为NULL。循环清楚地传达了这一点。

有一些非零NULL机器的历史示例:When was the NULL macro not 0?

但是,请注意,即使不要求NULL要求全为零,也可以保证在布尔表达式中使用NULL时的计算结果为false。因此,您可以安全地使用if(!ptr)来检查对malloc的调用是否成功。我在这个答案Is NULL always false?

中对此进行了解释

答案 1 :(得分:1)

的标准功能是 memset。从理论上讲,它不是100%可移植的,但是在实践中,它几乎不会引起任何实际问题,因此被广泛使用。

代替

for (int i = 0; i < array_length; i++) {
    array[i] = NULL;
}

您可以使用此功能:

memset(array, 0, array_length * sizeof(array[0]));

memset的第三个参数是要设置为零的内存长度(以字节为单位)。因此,ylu需要将数组长度乘以一个数组元素的大小sizeof(array[0])

现在,NULL可以是所有值都设置为0的值以外的其他值,在这种实现中,memset不能用于将所有指针都设置为NULL。但这只是理论上的问题,在过去的30年中,我从未见过将NULL与所有位都设置为0的值不同的实现。

关于第二个问题:

通常,将任何类型T的数组(可以是任意大小)中的所有值设置为某个特定值的标准方法是什么?

不,C中没有这样的东西,您需要循环执行。在C ++中,您可以执行以下操作。

答案 2 :(得分:1)

使用显式循环初始化数组是保证可以在所有平台上正常工作的唯一符合标准的方法。好的编译器应该能够将循环转换为目标平台上用于零初始化的更有效的方法,前提是确实用所有零位表示空指针。

如果可以假设所有位零都是空指针的正确表示(这几乎总是这种情况,但C标准并不能保证),则可以使用对memset的调用或更有效的方法,进行分配具有calloc()的数组:

Thing **array = calloc(array_length, sizeof(*array)); // initialize to all bits zero

在某些情况下,这比对memset的调用和calloc()的显式循环都更有效,在某些情况下,它们假定从操作系统获取的内存已经被初始化为零,就像这种情况出于安全原因,新映射的块的数量。

答案 3 :(得分:-1)

我认为,这应该可行。

int *arr[10] = {0}; // arr is array of size 10, where each element is pointer to an int.

这会将数组的每个元素初始化为0。

这也保证可以在所有平台上使用。