您还可以考虑使用辅助函数。
请参阅commit 45ccef8、commit 60566cb(2016 年 9 月 25 日)René Scharfe (rscharfe)。
(由 Junio C Hamano -- gitster -- 合并到 commit b1f0a85,2016 年 10 月 3 日)
它使用COPY_ARRAY, a safe and convenient helper 来复制数组,
补充ALLOC_ARRAY 和REALLOC_ARRAY。
因此,您可以使用COPY_ARRAY(temp, a, 1);,而不是memcpy(temp, a, sizeof(a));
用户只需指定来源、目的地和元素数量;自动推断元素的大小。
它检查大小和元素计数的乘积是否溢出。
推断的大小首先传递给st_mult,它允许除法
在编译时完成。
作为基本的类型安全检查,它确保源的大小和
目标元素是相同的。这是在编译时评估的
也是。
COPY_ARRAY 可以安全地使用NULL 作为源指针,如果 0 个元素是
被复制。
该约定在某些情况下用于初始化数组。
Raw memcpy(3) 不支持它——允许编译器
假设只有有效的指针被传递给它并且可以优化掉
NULL 在这样的电话之后进行检查。
#define COPY_ARRAY(dst, src, n) copy_array((dst), (src), (n), sizeof(*(dst)) + \
BUILD_ASSERT_OR_ZERO(sizeof(*(dst)) == sizeof(*(src))))
static inline void copy_array(void *dst, const void *src, size_t n, size_t size)
{
if (n)
memcpy(dst, src, st_mult(size, n));
}
它使用声明构建时依赖关系的macro BUILD_ASSERT_OR_ZERO 作为表达式(@cond 是编译时条件,必须为真)。
如果条件不成立或编译器无法评估,则编译将失败。
#define BUILD_ASSERT_OR_ZERO(cond) \
(sizeof(char [1 - 2*!(cond)]) - 1)
例子:
#define foo_to_char(foo) \
((char *)(foo) \
+ BUILD_ASSERT_OR_ZERO(offsetof(struct foo, string) == 0))
The inline function st_mult在commit 320d0b4中引入
static inline size_t st_mult(size_t a, size_t b)
{
if (unsigned_mult_overflows(a, b))
die("size_t overflow: %"PRIuMAX" * %"PRIuMAX,
(uintmax_t)a, (uintmax_t)b);
return a * b;
}
st_mult是检测size_t溢出的部分辅助函数,其中包括unsigned_mult_overflows
对我们提供给xmalloc 和朋友的size_t 变量执行计算可能很危险,因为整数溢出会导致我们分配的块比我们意识到的要小得多。
我们已经有unsigned_add_overflows(),但让我们添加
unsigned_mult_overflows()那个
/*
* Returns true if the multiplication of "a" and "b" will
* overflow. The types of "a" and "b" must match and must be unsigned.
* Note that this macro evaluates "a" twice!
*/
#define unsigned_mult_overflows(a, b) \
((a) && (b) > maximum_unsigned_value_of_type(a) / (a))
使用maximum_unsigned_value_of_type: helper for detecting unsigned overflow(来自commit 1368f6)
成语(a + b < a) 可以很好地检测无符号整数是否溢出,但更明确
unsigned_add_overflows(a, b)
可能更容易阅读。
定义这样一个宏,大致扩展为((a) < UINT_MAX - (b))。
因为扩展只在sizeof() 之外使用每个参数一次
表达式,与具有副作用的参数一起使用是安全的。
#define bitsizeof(x) (CHAR_BIT * sizeof(x))
#define maximum_unsigned_value_of_type(a) \
(UINTMAX_MAX >> (bitsizeof(uintmax_t) - bitsizeof(a)))
使用CHAR_BIT being the number of bits in char(取决于架构)
您可以查看 Git 2.23(2019 年第三季度)的示例
参见René Scharfe (rscharfe) 的commit 921d49b、commit 177fbab(2019 年 6 月 15 日)。
(由 Junio C Hamano -- gitster -- 合并于 commit e8d2590,2019 年 7 月 9 日)
使用COPY_ARRAY 复制数组
将memcpy(3) 的调用转换为使用COPY_ARRAY,这样可以缩短和
稍微简化了代码。