如何在C中检查分配数组中的空字段

Posted

技术标签:

【中文标题】如何在C中检查分配数组中的空字段【英文标题】:How to check for null fields in allocated array in C 【发布时间】:2022-01-05 19:04:42 【问题描述】:

我有一个分配的数组,需要遍历所有字段并比较非空值。这个数组中的值也可以是 0,这给我带来了一些麻烦。

int size = 4;
int *numbers = (int*) malloc(size * 4);

// Fill some fields
numbers[0] = 3;
numbers[1] = 0;
numbers[2] = 6;

// Search and find min value's index
int min = 0;
for (int i = 0; i < size; i++) 
    if (numbers[i] != NULL) 
        if (numbers[i] < numbers[min]) min = i;
     else 
        // Code if value is null here
    


printf("%d\n", min);

我不确定如何正确地与 NULL 进行比较。正确的方法是什么?

【问题讨论】:

在C中,NULL和0没有区别。 @Klas-Kenny 好吧...0 只是一个整数文字,而NULL((void *)0) 您确实不想int 值与NULL 进行比较,而您确实想与0 进行比较。 99.44% 的系统,NULL 为零,但这不是保证。此外,大多数系统都这样做:#define NULL ((void *) 0),因此编译器应该标记 int 值与指针的比较 @CraigEstey 但是可以保证,零整数文字,或这种转换为指针类型的文字等价于NULL,即使它的空指针的内部表示类型并非全为零。 C 中的整数变量不可为空,就像您在其他编程语言中习惯的那样。 【参考方案1】:

您分配的数组元素永远不会为 NULL。即使是从使用 free 函数中释放出来的内存也不是 NULL。 IT 可以指向任何东西,可能是您自己的程序地址空间或外部地址空间。

你的代码看起来不错。你没有分配给索引 3 的元素的值可以有垃圾但不能为 NULL

【讨论】:

不过,未初始化的值可以比较等于NULL @Arkku 如果我这样做 char *p=malloc(..) 那么它没有以必须指向某个垃圾值的方式进行统一化。在 C 或内存中,即使它是垃圾,它也有可能指向某些东西。所以从成功的 malloc 分配的内存不能有 (char*)0 或 NULL 旁注:我不完全确定,但我很少看到ur 代表youru 代表you 在SO [除了关于新手问题]。 SO != twitter?我见过其他人,例如 IMO、AFAIK、AFAICT、IIRC @user786 C 标准第 6.3.2.3.3 节将空指针常量定义为“值为 0 的整数常量表达式,或转换为 void * 类型的表达式”,因此 NULL 可以只是#define NULL 0,因此完全有可能,甚至很可能,内存中的“垃圾”值比较为零。此外,未初始化内存中的未定义值可以是任何位模式,因此即使您将其与具有非零位表示的运行时空指针(而不是NULL)进行比较,它仍然是可能的位模式之一可能在内存中。 而且在任何情况下,整个空值推测都不是重点,它只是众多值中的一个。在 OP 的 32 位机器中(基于分配 size * 4 内存),每个垃圾值都是 2³² 可能值之一,因此在这么多值中至少有 1 次机会与任何给定常数进行比较(并非所有值都是同样可能发生;事实上,它们在实践中可能是相当确定的)。当然,人们可以推测使用未初始化的值可能是未定义的行为,因此编译器理论上可以生成代码来做任何事情。【参考方案2】:

你的整体设计有缺陷。您不应将 NULL 视为一个全能的零值。 NULL 是一个特殊的指针 值,而不仅仅是一个整数。如果您将intNULL 进行比较,您将比较两种不同的类型,这不是一个好主意。此外,您将标量类型与指针类型进行比较,这更糟。

这个数组中的值也可以是 0,这给我带来了一些麻烦。

如果是这种情况,您不能将0 用作值和“非现值”的“标记”。问题是,你也不能使用NULL,因为它是不同的类型。如果您尝试使用它,编译器会警告您(或者至少应该警告您,如果您启用警告)。充其量,分配NULL 会将其隐式转换为int 并导致0,因为NULL 通常被定义为((void *)0),因此无法区分NULL 值和有效值。

为此,您必须保留INT_MININT_MAX 之间的值之一:

#include <limits.h>

enum  NOT_PRESENT = INT_MIN ;

int size = 4;
int *numbers = malloc(size * sizeof(int));

// Initialize all to NOT_PRESENT
for (int i = 0; i < size; i++)
    numbers[i] = NOT_PRESENT;

// Fill some fields
numbers[0] = 3;
numbers[1] = 0;
numbers[2] = 6;

// Search and find min value's index
int min = 0;

for (int i = 0; i < size; i++) 
    if (numbers[i] != NOT_PRESENT) 
        if (numbers[i] < numbers[min]) min = i;
     else 
        // Code if value is not present here
    


printf("%d\n", min);

【讨论】:

以上是关于如何在C中检查分配数组中的空字段的主要内容,如果未能解决你的问题,请参考以下文章

如何删除数组中的空元素[重复]

如何在 Python 中获取任意大小的空列表?

检查输入字段中的空值的正确方法是啥[重复]

如何在流分析中检查 JSON 属性中的空值?

MongoDB 检查 $switch 语句中的空字段

如何忽略 ExtJS 数据模型中的空字段?