我的头文件是
typedef struct vector vector;
vector * vector_create(size_t size);
c
文件:
vector * vector_create(size_t size){
if(size >= PTRDIFF_MAX)
return NULL;
//actual creation logic
}
我需要将vector
的大小限制为不超过PTRDIFF_MAX
,因为我需要从另一个向量中减去指向一个向量元素的指针。问题出在我要测试时
void test_create_vector_too_large(void){
#if SIZE_MAX >= PTRDIFF_MAX + 1
list * lst = list_create(((size_t) PTRDIFF_MAX) + 1);
assert(!lst);
#endif
}
此代码会产生大量警告
/home/kjroff/main.c:55:32: warning: integer overflow in preprocessor expression
#if SIZE_MAX >= PTRDIFF_MAX + 1
^
/home/kjroff/main.c:55:29: warning: the right operand of ">=" changes sign when promoted
#if SIZE_MAX >= PTRDIFF_MAX + 1
#if
宏的目的是检查ptrdiff_t
的上限是否超过size_t
的上限。如果它们相同,则此测试没有意义。但这是在PTRDIFF_MAX < SIZE_MAX
情况下发生的。
如何正确编写这样的断言?
答案 0 :(得分:4)
该比较通常是无用的,因为size_t
和ptrdiff_t
的宽度通常相同,但是size_t
是无符号的,而ptrdiff_t
是有符号的,所以SIZE_MAX
是必须大于PTRDIFF_MAX
。这不是C标准严格指定的,因为size_t
只是用于大小表达式的类型,尽管有意图,但并未明确指定它足以表示任何对象的大小。同样,ptrdiff_t
只是用于指针差异的类型,尽管有意图,但并未明确指定它足以代表所有指针的差异。
也就是说,您可以将比较更改为SIZE_MAX > PTRDIFF_MAX
,这与pmg所指出的等效。使警告安静的另一种方法是将1
更改为1u
,产生SIZE_MAX > PTRDIFF_MAX + 1u
。根据C 2018 6.10.1 4,在预处理中,整数类型的行为类似于intmax_t
和uintmax_t
,因此1u
的类型为uintmax_t
,因此{{1 }}将转换为PTRDIFF_MAX
,然后添加到uintmax_t
(不会溢出),并且比较将在两种1u
类型之间进行(避免警告)。
问题指出:“我需要将向量的大小限制为不超过PTRDIFF_MAX,因为我需要从另一个向量中减去指向一个向量元素的指针。”但是uintmax_t
的单位是一个字节,而size_t
的单位是一个数组元素。除非ptrdiff_t
类型为单个字节,否则将减去两个vector
指针的结果。即使在vector *
难以覆盖所有可能大小的受约束系统中,size_t
也应舒适地为两个ptrdiff_t
指针的差异留出空间,而不管底层数组的大小如何。因此测试vector *
似乎没有用。
答案 1 :(得分:2)
如何正确编写这样的断言?
代替
#if SIZE_MAX >= PTRDIFF_MAX + 1
减去(SIZE_MAX
至少为65535),所以不可能溢出。
#if SIZE_MAX - 1 >= PTRDIFF_MAX
或仅使用>
@pmg
#if SIZE_MAX > PTRDIFF_MAX