【发布时间】:2014-10-27 21:09:07
【问题描述】:
我正在修改从字节交换例程库1 获得的一段代码,并学习按位操作、#define 的用法、指针和类型转换:
#define __bswap_constant_32(x) \
((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \
(((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24))
在函数中使用 sn-p 可以按预期工作:
void swapbytes32(void *pt)
{
*((unsigned int *)pt) = ((( *((unsigned int *)pt) & 0xff000000) >> 24) | (( *((unsigned int *)pt) & 0x00ff0000) >> 8) | \
(( *((unsigned int *)pt) & 0x0000ff00) << 8) | (( *((unsigned int *)pt) & 0x000000ff) << 24));
}
例如调用
float x = 1.0;
swapbytes32((void*)(&x));
给出 x = 0x0 0 80 3f 并交换了 x = 0x3f 80 0 0
但请注意所有尴尬的类型转换。类型转换的正确用法让我感到困惑。在上面的函数中,我用它来抑制错误,例如:
在函数“swapbytes32”中:hex_testi_3.c:200:31:警告: 取消引用 'void *' 指针 [默认启用] *((unsigned int *)pt) = ((( *pt) & 0xff000000) >> 24) | (( *pt) & 0x00ff0000) >> 8) | \
这是我认为到目前为止我所理解的:
- 无法取消引用 void 指针,因为您不知道隐含类型的字节长度或有关如何在操作中使用数据的信息。
- 上面的类型转换告诉编译器将地址中的数据类型视为
unsigned int,但不会更改存储数据的按位结构。
我不完全确定的是为什么在某些情况下编译器会根据我执行类型转换的位置而犹豫,或者没有按预期执行转换。
如何使用上述#define 语句(或类似语句)对float 类型变量执行字节交换?
【问题讨论】:
-
我看不出宏版本应该如何工作;在
float和int之间执行&不会访问浮点数的表示!x必须是*(unsigned int *)y,这会重新引入别名问题。 -
@MattMcNabb 不,如果您尝试将
float传递给宏,则该宏根本不起作用,这就是问题所在。请参阅我的答案,了解似乎是使用广泛类型转换的解决方法,就像在上面的函数中一样。 -
更具体地说,您不能使用
bswap_constant_32(&x),而必须使用bswap_constant_32((unsigned int*)(&x))之类的东西
标签: c bit-manipulation c-preprocessor