C/GL: Using -1 as sentinel on array of unsigned integers
I am passing an array of vertex indices in som开发者_如何学编程e GL code... each element is a GLushort
I want to terminate with a sentinel so as to avoid having to laboriously pass the array length each time alongside the array itself.
#define SENTINEL ( (GLushort) -1 ) // edit thanks to answers below
:
GLushort verts = {0, 0, 2, 1, 0, 0, SENTINEL};
I cannot use 0 to terminate as some of the elements have value 0
Can I use -1?
To my understanding this would wrap to the maximum integer GLushort can represent, which would be ideal.
But is this behaviour guaranteed in C?
(I cannot find a MAX_INT equivalent constant for this type, otherwise I would be using that)
If GLushort
is indeed an unsigned type, then (GLushort)-1
is the maximum value for GLushort
. The C standard guarantees that. So, you can safely use -1
.
For example, C89 didn't have SIZE_MAX
macro for the maximum value for size_t
. It could be portably defined by the user as #define SIZE_MAX ((size_t)-1)
.
Whether this works as a sentinel value in your code depends on whether (GLushort)-1
is a valid, non-sentinel value in your code.
GLushort
is an UNSIGNED_SHORT
type which is typedefed to unsigned short
, and which, although C does not guarantee it, OpenGL assumes as a value with a 2^16-1 range (Chapter 4.3 of the specification). On practically every mainstream architecture, this somewhat dangerous assumption holds true, too (I'm not aware of one where unsigned short
has a different size).
As such, you can use -1, but it is awkward because you will have a lot of casts and if you forget a cast for example in an if()
statement, you can be lucky and get a compiler warning about "comparison can never be true", or you can be unlucky and the compiler will silently optimize the branch out, after which you spend days searching for the reason why your seemingly perfect code executes wrong. Or worse yet, it all works fine in debug builds and only bombs in release builds.
Therefore, using 0xffff
as jv42 has advised is much preferrable, it avoids this pitfall alltogether.
I would create a global constant of value:
const GLushort GLushort_SENTINEL = (GLushort)(-1);
I think this is perfectly elegant as long as signed integers are represented using 2's complement.
I don't remember if thats guaranteed by the C standard, but it is virtually guaranteed for most CPU's (in my experience). Edit: Appparently this is guaranteed by the C standard....
If you want a named constant, you shouldn't use a const
qualified variable as proposed in another answer. They are really not the same. Use either a macro (as others have said) or an enumeration type constant:
enum { GLushort_SENTINEL = -1; };
The standard guarantees that this always is an int
(really another name of the constant -1
) and that it always will translate into the max value of your unsigned type.
Edit: or you could have it
enum { GLushort_SENTINEL = (GLushort)-1; };
if you fear that on some architectures GLushort
could be narrower than unsigned int
.
精彩评论