什么时候可以返回 NULL 作为 C 函数的返回值?

Posted

技术标签:

【中文标题】什么时候可以返回 NULL 作为 C 函数的返回值?【英文标题】:When are you able to return NULL as the returning value of a C function? 【发布时间】:2017-04-18 05:40:11 【问题描述】:

我想知道您能否告诉我何时能够返回 NULL,作为 C 中函数的结果。

例如,int lenght() 不能返回 NULL,因为在 return 语句中期待 int

但是函数struct node* find(int key),在处理链表时允许我返回NULL。

【问题讨论】:

指针与非指针。 NULL 是一个空指针值。 ***.com/questions/27096623/… 这个链接会帮助你 【参考方案1】:

NULL 是一个指针值 - 或者更确切地说是一个空指针值。

NULL 表示函数找不到指针应该指向的位置——例如,如果你想打开一个文件,但它不起作用,你的文件指针返回为NULL。因此,您可以测试指针的值并检查它是否有效。

如果你正在编写一个例程

int length()

如果 length 无法读取您发送的任何内容的长度,则您可以返回一个负值 - 这是指示错误的一种方式,因为通常长度永远不会是负数....

【讨论】:

【参考方案2】:

这是约定的问题,您应该清楚地记住一个并记录它(至少在 cmets 中)。

有时指针确实应该始终指向有效地址(参见this intSwap 示例,两个参数都应该是有效指针)。在其他时候,它应该是这样一个有效的地址,或者是NULL。从概念上讲,指针类型按照惯例sum type(在真正的指针地址和特殊的NULL 值之间)。

请注意,C 语言没有强制某些给定指针始终有效且非空的类型(或符号)。顺便说一句,特别是使用 GCC,您可以 annotate a function 和 __attribute__ 使用 nonnull 来表示给定的参数永远不会为空。

一个典型的例子是<stdio.h>中的FILE*指针。 fopen 函数被记录为能够返回 NULL(失败时)或一些有效的指针。但是fprintf 函数需要一个 valid 指针(并将NULL 作为第一个参数传递给它是一些undefined behavior,通常是segmentation fault;而UB 实际上是bad) .

一些不可移植的程序甚至使用几个“特殊”的指针值(不应该被取消引用),例如(在 Linux/x86-64 上)#define SPECIAL_SLOT (void*)((intptr_t)-1)(我们知道在 Linux 上它永远不是有效地址)。然后我们可以约定一个指针是指向有效内存区域的有效指针,或NULLSPECIAL_SLOT(因此,如果被视为abstract data type,它是两个不同的无效指针@987654346 的总和类型@ 和 SPECIAL_SLOT 以及有效地址集)。另一个例子是MAP_FAILURE 作为Linux 上mmap(2) 的结果。

顺便说一句,当在 C 中使用指针来堆分配数据时(通过 malloc 间接获得),您还需要关于谁负责释放数据的约定(通过使用 free,通常通过提供的函数来释放数据及其所有内部内容)。

良好的 C 编程需要许多关于指针的显式约定,准确理解它们并妥善记录它们至关重要。在GTK 中查找示例[s]。另请阅读restrict

【讨论】:

【参考方案3】:

什么时候可以返回 NULL 作为 C 函数的返回值

一般来说,当且仅当函数返回指针类型:

T * function(<parameter definitions> | void>); /* With T being any valid type. */

还有其他一些极端情况,这取决于所使用的 C 实现。

【讨论】:

【参考方案4】:

NULL 绝对是一个指针。因此,如果您的函数预期返回一个指针,但由于某种原因不能,它应该返回明显的“无效指针”,即 NULL。

【讨论】:

@alk 标准:值为 0 的整数常量表达式,或转换为 void * 类型的此类表达式称为空指针常量。请不要告诉我“空指针常量”不是指针。 嗯,是的,很公平。【参考方案5】:

NULL 可以定义为 0(void*)0(参见 6.3.2.3p3 和 7.19p3)。

因此,它可能总是在返回指针类型的函数中用作返回值,并且根据实现,它可能在返回数值类型的函数中用作返回值,虽然后者是个坏主意,因为 NULL 预计将与指针关联使用。

【讨论】:

以上是关于什么时候可以返回 NULL 作为 C 函数的返回值?的主要内容,如果未能解决你的问题,请参考以下文章

如何为迭代器返回“null”值?

字符串作为c ++函数中的返回值

c语言中的RETURN()返回值是啥意思?

c++11 使用 std::map 作为返回值

C语言fopen函数和其参数

s.equals(s1)的返回值不是字符串的话 是啥