Sorry but I couldn't understand from your comments what is your position about ffi converting null pointers to nil. I doubt luajit would ever work on a platform for which NULL isn't zero[1], but that wouldn't even be an issue since the ffi already knows how to convert a nil to a NULL so it could as well do the reverse. Lemme put it another way: what object does the NULL address hold that the type system doesn't want us to trash, a foo* or a bar* ? :) [1] http://c-faq.com/null/machexamp.html On Tue, Jun 5, 2012 at 7:59 PM, Sean Conner <sean@xxxxxxxxxx> wrote: > It was thus said that the Great Cosmin Apreutesei once stated: >> >> In static languages people have to reserve a segment from the range of >> a scalar type for special values like "error" or "unknown". So they >> use -1 to signal an error case and the address 0 (aka NULL) to specify >> lack of a value. In C, NULL is just a convention. From the pov. of the >> language, the zero address is as valid as any other, hence you can't >> pass a NULL bar* for a foo*. But everybody on earth reserves the >> address 0 for the special meaning missing/empty/not-valid/unknown/etc. >> which is _the same meaning_ for foo* as it is for bar* hence it is >> _logically transferable_ from foo* to bar*, but C doesn't let you do >> that because it doesn't know anything about NULL since that's just a >> convention, necessary in any static-typed language. > > In C, the use of the value 0 in a pointer context converts that 0 to a > null pointer [1] of the type of 'void *' (the generic pointer in ANSI C). > Also in C, any pointer can be converted to a 'void *' with no cast, and a > 'void *' can be converted to any type of pointer with no cast. So the > following: > > foo__t *foo; > bar__t *bar; > > foo = malloc(5); > bar = foo; > > will cause a compiler error since you are trying to assign a 'foo__t *' to a > 'bar__t *'. But this: > > foo__t *foo; > void *p; > bar__t *bar; > > foo = malloc(5); > p = foo; > bar = p; > > will compile without error (or warnings). That's because the pointer of > 'foo__t *' goes through a 'void *' variable. So, you can't do: > > foo = (bar__t *)NULL; > bar = (foo__t *)NULL; > but you can do > > foo = NULL; > bar = NULL; > > And of course you can always do: > > foo = (foo__t *)bar; > bar = (bar__t *)foo; > > [1] There is a distinction between the value 0 used in a pointer context > in source code, and an actual "null" pointer as defined by the CPU > architecture [2]. Yes, many CPUs these days will also use the value > of 0 as an invalid pointer, but that's not mandated! There could be > an architecure where an invalid pointer is actually all ones. On > such a system, NULL is still defined as '0' [3] but internally the > compiler converts such a value to all ones to store in to the actual > pointer variable. > > [2] That is, if the CPU architecture actually *has* a concept of an > invalid pointer. If a CPU has no concept of an invalid pointer, > then a value is ussually used. It could be all zeros. It could be > all ones. It could be alternating ones and zeros. It just has to > be treated as an "invalid" address in software. > > [3] or sometimes '(void *)0' > >> In Lua we no longer have to revert to tricks like NULL. We don't think >> having a "nil string" incompatible with a "nil number" as a neat idea >> either. The ffi is a Lua API not a C API and deals with C APIs not >> with the C language, it doesn't have to copy C's world-view if it's >> not useful. This "guarding" against assigning a NULL foo* to a bar* is >> not a useful property in Lua (I think it's not useful in C either, you >> just can't have it otherwise in a static language). > > In Lua, values have types, not variables. And because of that, Lua can > make the distinction between 'undefined' and 'defined' (and thus, only has > one type of 'nil', which is 'nil). C doesn't have that distinction, except, > somewhat, with pointers and NULL. But just declaring a pointer in C: > > foo__t *foo; > > doesn't make it 'undefined' (per the Lua meaning)---the value is whatever > happens to be in the memory locations that make up the pointer. That could > be 0 (which doesn't imply an invalid pointer---that depends upon the > architecure); it could be 42, or it could be some random bit pattern. The > use of foo, prior to being initialized, is undefined (it may read/write some > memory somewhere; it could crash the program; again, it's architecturally > dependent). > > -spc > >