这个问题可能看起来很傻,但请指导我,我有一个函数将长数据转换为char数组
void ConvertLongToChar(char *pSrc, char *pDest)
{
pDest[0] = pSrc[0];
pDest[1] = pSrc[1];
pDest[2] = pSrc[2];
pDest[3] = pSrc[3];
}
Run Code Online (Sandbox Code Playgroud)
我将上述函数称为这样
long lTemp = (long) (fRxPower * 1000);
ConvertLongToChar ((char *)&lTemp, pBuffer);
Run Code Online (Sandbox Code Playgroud)
哪个工作正常.我需要一个类似的功能来反转过程.将char数组转换为long.我不能使用atol或类似的功能.
我想知道以下代码是否是一种可接受的方法,以不破坏严格别名规则的方式处理类型惩罚.我意识到这个方法依赖于GCC编译器扩展,所以没有必要指出这一点.
template <class output_type, class input_type>
inline output_type punning_cast(const input_type& input)
{
static_assert(std::is_pod<output_type>::value, "output_type for punning_cast must be POD");
static_assert(std::is_pod<input_type>::value, "input_type for punning_cast must be POD");
static_assert(sizeof(output_type) == sizeof(input_type), "input_type and output_type must be the same size");
typedef output_type __attribute__((may_alias)) output_type_may_alias;
return *reinterpret_cast<const output_type_may_alias*>(&input);
}
template <class output_type, class input_type>
inline output_type punning_cast(const input_type* input)
{
static_assert(std::is_pod<output_type>::value, "output_type for punning_cast must be POD");
static_assert(std::is_pod<input_type>::value, "input_type for punning_cast must be POD");
typedef output_type __attribute__((may_alias)) output_type_may_alias;
return *reinterpret_cast<const output_type_may_alias*>(input);
}
Run Code Online (Sandbox Code Playgroud)
用法示例:
uint32_t …Run Code Online (Sandbox Code Playgroud) 我想以下列格式打印64位十六进制数据:
0x1111_2222_3333_4444
Run Code Online (Sandbox Code Playgroud)
我可以想到以下几点:
#define FIRST_MASK 0xFFFF000000000000
#define SECOND_MASK 0x0000FFFF00000000
#define THIRD_MASK 0x00000000FFFF0000
#define FOURTH_MASK 0x000000000000FFFF
val = 0x1111222233334444
printf("0x%04x_%04x_%04x_%04x\n", \
(unsigned int)((val & FIRST_MASK) >> 48),
(unsigned int)((val & SECOND_MASK) >> 32),
(unsigned int)((val & THIRD_MASK) >> 16),
(unsigned int)(val & FOURTH_MASK)
);
Run Code Online (Sandbox Code Playgroud)
是否有简单(或可能更干净)的方法来实现这一目标?
我从网络接收缓冲区,该缓冲区被转换为32位字的数组.我有一个单词被我的界面文档定义为ieee float.我需要从缓冲区中提取这个单词.在不调用转换的情况下从一种类型转换为另一种类型很困难.这些位已经符合ieee浮点标准,我不想重新排列任何位.
我的第一次尝试是将地址转换uint32_t为a void*,然后将其转换void*为a float*,然后取消引用为float:
float ieee_float(uint32_t f)
{
return *((float*)((void*)(&f)));
}
Run Code Online (Sandbox Code Playgroud)
错误:解除引用类型惩罚指针将破坏严格别名规则[-Werror = strict-aliasing]
我的第二次尝试是这样的:
float ieee_float(uint32_t f)
{
union int_float{
uint32_t i;
float f;
} tofloat;
tofloat.i = f;
return tofloat.f;
}
Run Code Online (Sandbox Code Playgroud)
然而,街上的一句话是,工会完全不安全.从最近没有编写的联合成员读取它是未定义的行为.
所以我尝试了更多的C++方法:
float ieee_float(uint32_t f)
{
return *reinterpret_cast<float*>(&f);
}
Run Code Online (Sandbox Code Playgroud)
错误:解除引用类型惩罚指针将破坏严格别名规则[-Werror = strict-aliasing]
我的下一个想法是"搞砸它.为什么我要处理指针呢?" 并尝试过:
float ieee_float(uint32_t f)
{
return reinterpret_cast<float>(f);
}
Run Code Online (Sandbox Code Playgroud)
错误:从'uint32_t {aka unsigned int}'类型无效转换为'float'类型
有没有办法在不触发警告/错误的情况下进行转换?我用g ++编译-Wall -Werror.我宁愿不接触编译器设置.
我标记了C,因为c解决方案是可以接受的.
我读到这个代码是根据c标准未定义但我无法找到原因.它在gcc 8.1.0和clang-6.0中编译没有错误并打印1.
代码如下:
#include <stdio.h>
int main()
{
union {
int i;
short s;
} u;
u.i = 42;
u.s = 1;
printf("%d\n", u.i);
return 0;
}
Run Code Online (Sandbox Code Playgroud) 在整数和整数数组之间进行类型校正是否合法?
具体代码:
#include <nmmintrin.h>
#include <stdint.h>
union Uint128 {
__uint128_t uu128;
uint64_t uu64[2];
};
static inline uint_fast8_t popcnt_u128 (__uint128_t n)
{
const union Uint128 n_u = {.uu128 = n};
const uint_fast8_t cnt_a = _mm_popcnt_u64(n_u.uu64[0]);
const uint_fast8_t cnt_b = _mm_popcnt_u64(n_u.uu64[1]);
const uint_fast8_t cnt = cnt_a + cnt_b;
return cnt;
}
Run Code Online (Sandbox Code Playgroud) 我想使用 RGBA 值表示 32 位数字,使用联合生成该数字的值是否可移植?考虑这个 C 代码;
union pixel {
uint32_t value;
uint8_t RGBA[4];
};
Run Code Online (Sandbox Code Playgroud)
这编译得很好,并且我喜欢使用它而不是一堆函数。但这安全吗?
我需要将IEEE单精度浮点数写入特定地址的32位硬件寄存器.为此,我需要将float类型的变量转换为无符号整数.我可以像这样得到整数表示:
float a = 2.39;
unsigned int *target;
printf("a = %f\n",a);
target = &a;
printf("target = %08X\n",*target);
Run Code Online (Sandbox Code Playgroud)
返回:
a = 2.390000
target = 4018F5C3
Run Code Online (Sandbox Code Playgroud)
都好.但是这会导致编译器警告"cast.c:12:警告:从不兼容的指针类型分配"
有没有其他方法可以做到这一点,不会产生警告?这是针对特定的硬件,我不需要处理不同的字节顺序等,并且我不想因为性能原因而循环遍历每个字符串,因为其他一些问题往往会提示.看起来您可以在C++中使用reinterpret_cast,但我使用的是C语言.
我不太明白以下代码的输出
union foo
{
int a;
double b;
};
int main()
{
foo f;
f.b = 12.0;
cout << f.b << endl;
f.a = 69;
cout << f.b << endl;
cout << f.a << endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
为什么打印12 12 69
如果我没弄错的话,第二个12应该是垃圾.我正在使用Visual Studio 2010.
我只是对此感到好奇,但找不到任何相关内容。它使用十六进制是否有原因,或者只是因为它最初是这样写的?
代码如下供参考。
float Q_rsqrt( float number )
{
long i;
float x2, y;
const float threehalfs = 1.5F;
x2 = number * 0.5F;
y = number;
i = * ( long * ) &y;
i = 0x5f3759df - ( i >> 1 );
y = * ( float * ) &i;
y = y * ( threehalfs - ( x2 * y * y ) );
// y = y * ( threehalfs - ( x2 * y * y …Run Code Online (Sandbox Code Playgroud)