什么时候可以返回 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 上它永远不是有效地址)。然后我们可以约定一个指针是指向有效内存区域的有效指针,或NULL
或SPECIAL_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 函数的返回值?的主要内容,如果未能解决你的问题,请参考以下文章