void指针安全吗?

时间:2013-06-22 23:27:12

标签: c void-pointers bit-shift

我正在研究无符号整数类型的按位运算。我想为uint8_t,uint16_t,...,uint64_t类型编写左循环移位函数。

我的解决方案是:

(void*) left_circular_shift(void* number, size_t size);

如果size为64,我将void *转换为uint64_t等,但许多程序员避免使用void *。我应该为所有无符号整数类型实现该函数吗?

4 个答案:

答案 0 :(得分:1)

在您的情况下,您不能使用void *。如果你的泛型函数无效*你将无法测量你得到的大小(它如何知道你的数字在哪里结束?),所以你将无法将其强制转换。

关于Void *是“安全的”:你可能听说它“不安全”的原因是因为它是一个通用的无类型指针,它要求你准确地知道你正在处理什么样的数据用(你需要把它扔掉)。因此,如果不小心使用,它更容易引起意外和奇怪的错误。

这样做的简单方法是为每个使用一个函数。与其他人建议的一样,另一种选择是使用通用宏,关于这一点,您可能会对此感兴趣:http://www.ibm.com/developerworks/linux/library/l-gcc-hacks/index.html

答案 1 :(得分:1)

在C ++中,为所有无符号类型实现此函数是有意义的(保持相同的函数名称)。在C语言中,这是不可能的,但您可以为所有类型创建不同的函数,例如left_circular_shift_64等。

如果您想保留自己的界面,则应将void*转换为uint64_t*(而不是uint64_t)。以字节为单位指定size可能也很有用,而不是位。然后可以使用以下结构:

uint64_t value;
left_circular_shift(&value, sizeof(value));

例如,如果value的类型更改为uint32_t,这将有所帮助。

即使此选项有效且“安全”,我建议对每种类型使用不同的函数。支持此选项的一些原因:

  • 不可能将错误的数据传递给该函数,例如floatstruct或对象。
  • 不可能将不正确的尺寸传递给该功能,例如62.因此,如果函数有奇怪的输入,你不需要发明该做什么。
  • 您不需要保持两个参数(指针和大小)都清晰,这样可以减少错误的可能性。
  • 在C ++中,如果需要为这些类型实现移位操作,则可能会将void*转换为某些复杂类型(例如,具有多重继承的类)。

答案 2 :(得分:1)

对于这样的基本任务,根本没有理由使用指针类型。使用

inline
uintmax_t left_circular_shift(uintmax_t number, size_t size) {
  return /* your implementation goes here */
}

在头文件中,

extern inline uintmax_t left_circular_shift(uintmax_t number, size_t size);

在一个.c文件中。

然后,在size为常量的情况下,现代编译器应该能够内联调用。

答案 3 :(得分:0)

由于您需要取消引用void指针以移动指向的数字,因此不允许这样做,因为例如指向不同大小的数字的指针可能以不同方式对齐。 在不知道更多细节的情况下,这可能是宏适合的情况 - 这可能会改变您的数字变量,如果这是您想要的。