C/GL: Использование -1 в качестве Sentinel на массиве неподписанных целых чисел.
-
28-10-2019 - |
Вопрос
Я передаю массив индексов вершины в некотором коде GL ... каждый элемент - глюшера
Я хочу прекратить ссором, чтобы избежать трудолюбивого прохождения длины массива каждый раз вместе с самим массивом.
#define SENTINEL ( (GLushort) -1 ) // edit thanks to answers below
:
GLushort verts = {0, 0, 2, 1, 0, 0, SENTINEL};
Я не могу использовать 0 для прекращения, так как некоторые элементы имеют значение 0
Могу я использовать -1?
Насколько я понимаю, это может представить максимальное целое число, что будет идеально.
Но гарантировано ли это поведение в C?
(Я не могу найти эквивалентную константу max_int для этого типа, иначе я бы это использовал)
Решение
Если GLushort
это действительно беспигнутый тип, тогда (GLushort)-1
максимальное значение для GLushort
. Стандарт C гарантирует, что. Анкет Итак, вы можете безопасно использовать -1
.
Например, у C89 не было SIZE_MAX
макрос для максимального значения для size_t
. Анкет Пользователь может быть портильно определен как #define SIZE_MAX ((size_t)-1)
.
Работает ли это в качестве значения страдания в вашем коде, зависит от того, (GLushort)-1
является достоверным, несениновым значением в вашем коде.
Другие советы
GLushort
является UNSIGNED_SHORT
тип, который напечатан на unsigned short
, и что, хотя и не гарантирует Это, OpenGL предполагает как значение с диапазоном 2^16-1 (глава 4.3 спецификации). На практически каждой основной архитектуре это несколько опасное предположение также верно (я не знаю, где там, где unsigned short
имеет другой размер).
Как таковой, вы Можно Используйте -1, но это неловко, потому что у вас будет много актеров, и если вы забудете актерский состав, например, в if()
утверждение, вы можете быть счастливый и получить предупреждение компилятора о «сравнении никогда не может быть правдой», или вы можете быть несчастливый И компилятор молча оптимизирует ветвь, после чего вы проводите дни на поиски причины, по которой ваш, казалось бы, идеальный код выполняется неправильно. Или, что еще хуже, все работает нормально в сборке отладки, и только бомбы в сборке выпуска.
Поэтому использование 0xffff
Как сообщил JV42, очень предпочтительнее, он избегает этой ловушки Alltogether.
Я бы создал глобальную постоянную ценность:
const GLushort GLushort_SENTINEL = (GLushort)(-1);
Я думаю, что это совершенно элегантно, если подписанные целые числа представлены с использованием комплемента 2.
Я не помню, гарантировано ли это стандартом C, но это практически гарантируется для большинства процессоров (по моему опыту).Редактировать: Попад. Это является гарантированно стандартом C ....
Если вы хотите именованную константу, вы не должны использовать const
квалифицированная переменная, как предложено в другом ответе. Они действительно не такие. Используйте либо макрос (как сказали другие), либо константу типа перечисления:
enum { GLushort_SENTINEL = -1; };
Стандарт гарантирует, что это всегда int
(Действительно другое имя постоянной -1
) и что это всегда будет переходить в максимальное значение вашего типа без знака.
Редактировать: Или вы можете иметь это
enum { GLushort_SENTINEL = (GLushort)-1; };
Если вы боитесь этого на некоторых архитектурах GLushort
может быть более узким, чем unsigned int
.