Search code examples
cluanullluajit

NULL equals 0 in C, so should I treat both values like a nil?


Afaik NULL can be (or really is, at least in my stdlib implementation) #define'd as:

#define NULL ((void*)0)

also, https://stackoverflow.com/a/924683/668125 states that in C++ NULL is transparently cast to/from ((int)0) (which is the reason to use std::nullptr in C++ instead, since that has a real nil type/value pair thanks to the nullptr_t opaque typedef).

So, I'm currently developing a LuaJIT library and want to provide a helper function to check if a value is nil/NULL/whatever (=a value meaning nil but maybe not of type nil).

currently, that's:

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

but, a (NULL==0) in C would be true, as verified by this snippet printing true on my system:

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

so should I go for this definition of a "nil meaning value" instead?

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

TL;DR: in C, NULL is equal to 0, while in LuaJIT's FFI, no two pairs of nil, ffi.NULL, 0 are equal; so when defining what value should be considered a "nil like value" when dealing with 3rd party C libs, shall I include 0 or only nil or ffi.NULL?

Disclaimer: I'm afraid this might be considered an "opinion based question", so, in that case, I'll refine the question: Which behavior would more likely produce correct result, ignoring the fact that it could be considered good or bad style (so yes, if it's bad style but this particular style flaw is consistent between >50% of common libs, it's the way I'll have to do it)?


Solution

  • value == nil will return true if value is a NULL cdata object.

    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
    

    Thus, there's no point in your ffi.nil function. Just do if value == nil.

    Note:

    1. if value then won't work, because value is a cdata object and therefore evaluates to true, even though it is equal to nil. It's a bit confusing, but that's simply the way it is.

    2. Replacing builtin functions and modifying builtin library tables is usually bad practice. You should define it as a local function instead, or as a library function instead.