2017-10-28 200 views
2

我有这个功能接受int *为参数,并改变其第n位为1或0碳多重数据类型

void change_nth_bit(int *value, uint8_t bit, uint8_t n) { 
    (*value) ^= (-bit^(*value)) & (1U << n); 
} 

我可以保证,这将作为值可以是类型:

  • * uint8_t
  • *字符
  • * uint16_t

或者我应该为每个数据类型的函数?

+1

不,你不能让一个通用的函数,它的指针到t不同大小的类型。这种方式就是疯狂(和未定义的行为)。 –

回答

3

你不能使用单一功能,你需要多个功能。

否则,访问(*value)该是一个整数指针指向uint8_t对象,即

// This code is broken 
unit8_t val = 0xC4; 
change_nth_bit((int*)&val, 3, 1); 
//    ^^^^^^ 
//    | 
// Invalid ------+ 

将导致未定义的行为。

请注意,如果你把这个代码在宏(用宏参数引用代替指针后),你应该能达到预期的效果,而不必重复代码:

#define CHANGE_NTH_BIT(v,b,n) (v) ^= (-(b)^(v)) & (1U << (n)) 
+0

感谢您的澄清!所以我可以只写这个宏,并将它与任何数据类型一起调用,就像它是一个函数一样? –

+0

@PaulLemarchand是的。这比安装函数更安全,因为'v'可以被评估两次,但是你可以用任何数据类型来调用它。 – dasblinkenlight

+0

@PaulLemarchand是的。这比安装函数更安全,因为'v'可以被评估两次,但是你可以用任何数据类型来调用它。 – dasblinkenlight

1

假设指针双关语为安全和little endian(这是大多数系统上)

void cnb(void *val, size_t bit, int value) 
{ 
    uint8_t *ptr = val; 

    ptr += bit >> 3; 
    if(val) *ptr |= (!!val) << (bit & 7); 
     else *ptr &= ~((!!val) << (bit & 7)); 
} 

https://godbolt.org/g/HBEKme

+0

谢谢,我已经按照@dasblinkenlight的建议将我的代码更改为宏。可能也会研究这一点。 –

+0

@Paul Lemarchand这种“棘手”的分配方式比“notmal”重置和设置methot效率低。它看起来更聪明:) https://godbolt.org/g/2XFeGM –

+0

我看到,确实有更少的汇编指令。谢谢你的提示 ! –