C/GL:使用-1作为无符号整数数组的哨兵
我正在传递一些GL代码中的顶点索引数组。。。每个元素都是一个短元素 我希望以哨兵结束,以避免每次都要费力地沿着阵列本身传递阵列长度C/GL:使用-1作为无符号整数数组的哨兵,c,arrays,opengl-es-2.0,unsigned-integer,sentinel,C,Arrays,Opengl Es 2.0,Unsigned Integer,Sentinel,我正在传递一些GL代码中的顶点索引数组。。。每个元素都是一个短元素 我希望以哨兵结束,以避免每次都要费力地沿着阵列本身传递阵列长度 #define SENTINEL ( (GLushort) -1 ) // edit thanks to answers below : GLushort verts = {0, 0, 2, 1, 0, 0, SENTINEL}; 我无法使用0终止,因为某些元素的值为0 我能用-1吗 据我所知,这将包装到GLushort可以表示的最大整数,这将是理想的 但是这种行
#define SENTINEL ( (GLushort) -1 ) // edit thanks to answers below
:
GLushort verts = {0, 0, 2, 1, 0, 0, SENTINEL};
我无法使用0终止,因为某些元素的值为0
我能用-1吗
据我所知,这将包装到GLushort可以表示的最大整数,这将是理想的
但是这种行为在C语言中有保证吗
(我找不到此类型的MAX_INT等效常量,否则我将使用该常量)我将创建一个全局值常量:
const GLushort GLushort_SENTINEL = (GLushort)(-1);
我认为这是完美的,只要有符号整数是用2的补码表示的
我不记得C标准是否保证了这一点,但根据我的经验,大多数CPU实际上都保证了这一点。
编辑:Appparently这是由C标准保证的。
GLushort
是一种无符号SHORT
类型,其类型定义为无符号SHORT
,尽管C不保证,但OpenGL假定其值的范围为2^16-1(本规范第4.3章)。在几乎所有主流体系结构上,这种有点危险的假设也成立(我不知道unsigned short
的大小不同)
因此,您可以使用-1,但这很尴尬,因为您将有很多强制转换,如果您忘记了一个强制转换,例如在if()
语句中,您可能会幸运地得到一个关于“比较永远不可能为真”的编译器警告,或者您可能不幸运,编译器会默默地优化分支,在此之后,您将花费数天的时间寻找看似完美的代码执行错误的原因。或者更糟糕的是,它在调试版本中运行良好,只在发布版本中爆炸
因此,使用jv42建议的
0xffff
更可取,它可以避免这个陷阱。如果GLushort
确实是无符号类型,那么(GLushort)-1
是GLushort
的最大值。因此,您可以安全地使用-1
例如,C89没有为SIZE\u t
的最大值设置SIZE\u MAX
宏。用户可以将其便携式定义为#define SIZE_MAX((SIZE_t)-1)
这是否作为代码中的哨兵值,取决于
(GLushort)-1
在代码中是否是有效的非哨兵值。如果需要命名常量,则不应使用另一个答案中建议的const
限定变量。他们真的不一样。使用宏(如其他人所说)或枚举类型常量:
enum { GLushort_SENTINEL = -1; };
标准保证这始终是一个int
(实际上是常量的另一个名称-1
),并且它始终将转换为无符号类型的最大值
编辑:或者你可以拥有它
enum { GLushort_SENTINEL = (GLushort)-1; };
如果您担心在某些体系结构上,
GLushort
可能比unsigned int
窄,那么即使使用不使用两个补码表示的机器,C标准也能保证它的正确性。@SCM:我想您错过了其中的类型:“const GLushort GLushort_SENTINEL=(GLushort)(.1);”short
不是2字节的架构似乎分为三大类:旧的超互斥器、古老的计算机和DSP。然而,如果你比较(GLushort)x==GLushort\u SENTINEL
,你会调用“未定义的行为”,GCC至少总是会产生false
/0。@Dietrich,为什么这应该是未定义的行为?很抱歉,它通常不会调用未定义的行为(尽管在short
和int
具有相同范围的系统上会调用)。我错过了integer促销的一个细微差别。但是,在标准定义了行为的系统上,比较总是返回false
。(比较(unsigned)x==(int)y
总是未定义的,这是我最初的想法。)其要点是对于GLushort x
,x==(GLushort)-1
总是按照询问者想要的方式工作,x==-1
总是错误的(除了在深奥系统上,它是未定义的)。好的,我收回这一点,这不是未定义的行为。我总是忘记在整数升级之后,“通常的算术转换”适用。整数提升(§6.3.1.1)仅从级别较低的类型提升为int
和无符号
,优先选择int
,除非它不能表示原始类型的所有可能值。由于unsigned
和int
始终具有相同的秩(因为unsigned
是unsigned int
的缩写,natch),有符号值转换为unsigned(§6.3.1.8)。这意味着UINT\u MAX==-1
但是USHRT\u MAX!=-1
在深奥的平台上除外。测试证实了这一点。你们真是太棒了!谢谢