在C中,NULL等于0,所以我应该将这两个值视为零吗?

时间:2014-07-20 06:20:29

标签: c lua null luajit

Afaik NULL可以(或者至少在我的stdlib实施中)#define代表:

#define NULL ((void*)0)

另外,https://stackoverflow.com/a/924683/668125表示C ++中的NULL透明地转换为((int)0)(这是在C ++中使用std::nullptr的原因,因为它有一个真正的nil类型/价值对归功于nullptr_t opaque typedef)。

所以,我正在开发一个LuaJIT库,并希望提供一个帮助函数来检查值是nil / NULL / what(=值意思 nil但可能不属于nil类型。

目前,那是:

function ffi.nil(value)
  return value==nil or value==ffi.NULL
end

但是,C中的(NULL==0)为真,我的系统上的代码段打印true验证了这一点:

#include <stdio.h>
#include <stdlib.h>
void main(void){
  if(NULL==0)
    printf("true\n");
  else
    printf("false\n");
}

那么我应该选择“nil含义值”的定义吗?

function ffi.nil(value)
  return value==nil or value==ffi.NULL or value==0
end
C中的

TL; DR:NULL等于0,而在LuaJIT的FFI中,没有两对nil, ffi.NULL, 0相等;因此,当在处理第三方C库时定义哪个值应被视为“nil类似值”时,我应该包括0还是仅nil or ffi.NULL

免责声明:我担心这可能会被视为“基于意见的问题”,因此,在这种情况下,我会改进这个问题:哪种行为更有可能产生正确的结果,而忽略了可以考虑的事实好的或坏的风格(所以是的,如果它的风格不好,但这种特殊的风格缺陷在普通文库的50%之间是一致的,那就是我必须这样做的方式)?

2 个答案:

答案 0 :(得分:5)

如果value == nil是NULL cdata对象,

value将返回true。

LuaJIT 2.1.0-alpha -- Copyright (C) 2005-2014 Mike Pall. http://luajit.org/
JIT: ON SSE2 SSE3 SSE4.1 fold cse dce fwd dse narrow loop abc sink fuse
> ffi = require "ffi"
> print(ffi.new("void*", nil) == nil)
true

因此,ffi.nil函数中没有任何意义。只需if value == nil

注意:

  1. if value then无法正常工作,因为value是一个cdata对象,因此评估为true,即使它等于nil。这有点令人困惑,但这只是它的方式。

  2. 替换内置函数和修改内置库表通常是不好的做法。您应该将其定义为本地函数,而不是库函数。

答案 1 :(得分:1)

<强> 1。关于C中的NULL

首先,我分析了C中NULL的内容。

在标准C99文件中,我们可以阅读,分别为6.3.2.3:

  

值为0的整型常量表达式,或此类表达式   强制转换为void *,称为空指针常量。

这定义了空指针常量。 在每个实现中,宏NULL必须被定义为空指针常量。

  

宏NULL在(和其他头文件)中定义为空指针常量;

这意味着#define NULL 0(void*)0(void*)0 void*只有两种可能性。

我们看到,null常量表达式有两种形式,但不一定被视为空指针
转换为空指针常量的指针类型将带来类型的空指针 表单==本身是类型为!=的空指针。

  

任何两个空指针都比较相等。

等于运算符是NULLNULL,它们允许通过遵循我不在此处复制的精确规则来比较算术值和指针值。但是,我会引用这个:

  

[允许相等运算符]一个操作数是指针和   另一个是空指针常量。

因此,可以将每个指针与NULL进行比较以检查相等性。

(注意不仅允许指向对象的指针,而且还可以将指向函数的指针与NULL进行比较)。

  

如果一个操作数是指针而另一个是空指针常量,   空指针常量将转换为指针的类型。

这描述了如何执行与0的比较,以防万一。

  

两个指针比较相等,如果两者都是空指针[...]

我无法在标准中找到正确的位置,当与空指针常量0进行比较时,某种类型的空指针会给出 true 。但是,无论如何,显然这是预期的行为。

我们可以得出结论,与nil比较的每个空指针都给出了真,NULL不是空指针,而是整数常量。 “真实”空指针值不是由C的语法以任何显式方式表示,而是仅以间接形式表示。

<强> 2。在LUA做什么

嗯,我不认识Lua ,但是因为你,我环顾四周。 Lua和C之间有一些关系。

C在(void*)0的精神中没有保留字来表示空值 常量0总是一个整数,而不是指针,但C将它与具有空值的指针进行比较 0宏有时被定义为NULL,它是一个指针,但有时可以定义为NULL,它也是一个整数。
由于.NULL是一个宏,因此并不重要。

所以,我认为你所考虑的选项都没有反映出C.中发生的事情 但是,通常,使用NULL来指定C中的空指针 我在Lua中看到了C函数,以某种特殊方式调用 另一方面,我从你的问题中推断出可以调用某种NULL的东西。

第3。答案

我的意见是你的选择必须是{{1}} 由于您计划使用该函数来检查C中的空指针,因此考虑到在C中,返回指针的函数也可以返回空指针,而空指针又可以作为参数传递给另一个函数。登记/> 如果期望您的函数也返回非空值和/或与C指针相关的其他函数合作,则必须提供值{{1}}。
这将是我的选择。

无论如何,我道歉,因为我猜这里,因为我不知道Lua。