请考虑以下代码段:
union
{
int a;
float b;
};
a = /* ... */;
b = a; // is this UB?
b = b + something;
Run Code Online (Sandbox Code Playgroud)
一个工会会员的任命是否有效?
我正在使用HIDAPI将一些数据发送到USB设备.这个数据只能作为字节数组发送,我需要在这个数据数组中发送一些浮点数.我知道浮点数有4个字节所以我认为这可能有用:
float f = 0.6;
char data[4];
data[0] = (int) f >> 24;
data[1] = (int) f >> 16;
data[2] = (int) f >> 8;
data[3] = (int) f;
Run Code Online (Sandbox Code Playgroud)
后来我所要做的就是:
g = (float)((data[0] << 24) | (data[1] << 16) | (data[2] << 8) | (data[3]) );
Run Code Online (Sandbox Code Playgroud)
但测试这一点告诉我,像float返回的线总是4.我的代码出了什么问题,我怎么能正确地做到这一点(即在4个字节字节中打破浮点内部数据并在以后重建同一个浮点数)?
编辑:
我能够用以下代码完成此任务:
float f = 0.1;
unsigned char *pc;
pc = (unsigned char*)&f;
// 0.6 in float
pc[0] = 0x9A;
pc[1] = 0x99;
pc[2] = 0x19;
pc[3] = 0x3F; …Run Code Online (Sandbox Code Playgroud) 我目前正在从事一个项目,其中提供了以下结构。我的工作是 C++,但该项目同时使用 C 和 C++。C 和 C++ 都使用相同的结构定义。
typedef struct PacketHeader {
//Byte 0
uint8_t bRes :4;
uint8_t bEmpty :1;
uint8_t bWait :1;
uint8_t bErr :1;
uint8_t bEnable :1;
//Byte 1
uint8_t bInst :4;
uint8_t bCount :3;
uint8_t bRres :1;
//Bytes 2, 3
union {
uint16_t wId; /* Needed for Endian swapping */
struct{
uint16_t wMake :4;
uint16_t wMod :12;
};
};
} PacketHeader;
Run Code Online (Sandbox Code Playgroud)
根据结构实例的使用方式,结构所需的字节序可以是大端或小端。由于结构的前两个字节都是单个字节,因此当字节序更改时不需要更改这些字节。字节 2 和 3 存储为单个uint16_t,是我们需要交换以实现所需字节顺序的唯一字节。为了实现字节序交换,我们一直在执行以下操作:
//Returns a constructed instance of PacketHeader with relevant fields …Run Code Online (Sandbox Code Playgroud) 最近,在将我们的应用程序从gcc-5.3移植到8.2时,我们注意到一个奇怪的行为破坏了我们的应用程序。
简而言之,似乎gcc-8.2删除了我们的“ if分支,它比较2个无符号整数”之一,甚至没有发出警告。
我们使用相同的编译选项尝试了g ++ 5.3,g ++ 7.4和g ++ 8.2,只有g ++ 8.2出现了此问题。下面将显示一个简短示例。
#include <iostream>
#include <cstdint>
#include <cstdlib>
#include <cstring>
using namespace std;
struct myunion {
myunion(uint32_t x) {
_data.u32 = x;
}
uint16_t hi() const { return _data.u16[1]; }
uint16_t lo() const { return _data.u16[0]; }
union {
uint16_t u16[2];
uint32_t u32;
} _data;
};
__attribute__((noinline)) void printx1x2(uint32_t x1, uint32_t x2) {
cout << "x1: " << x1 << endl;
cout << "x2: " << x2 << endl;
} …Run Code Online (Sandbox Code Playgroud) 在这个答案的评论中,据说使用如下的联合将整数分割成它们的字节将是未定义的行为.在那个地方给出的代码是相似的,虽然与此不相同,请注意我是否更改了代码的未定义行为相关方面.
union addr {
uint8_t addr8[4];
uint32_t addr32;
};
Run Code Online (Sandbox Code Playgroud)
到目前为止,我认为这将是一个很好的做法,addr = {127, 0, 0, 1};并得到相应 uint32_t的回报.(我承认根据我的系统的字节顺序,这可能产生不同的结果.但问题仍然存在.)
这是未定义的行为吗?如果是这样,为什么?(我不知道C++中的UB是什么意思是访问非活动的联盟成员.)
C99
C++ 03
然而
结论
uint8_t[4]和uint32_t不是同一类型(我猜,一个严格的混叠的东西)(加上两个都不是POD结构/联合)上面确实是UB?C++ 11
我有2个进程sigserver和sigclient.sigserver等待信号到来,sigclient将数据(int + char)发送到sigserver.
sigserver.c
void sighand(int signo, siginfo_t *info, void *extra)
{
void *ptr_val = info->si_value.sival_ptr;
int int_val = info->si_value.sival_int;
printf("Signal: %d, value: [%d] %s\n", signo, int_val, (char*)ptr_val);
}
int main()
{
struct sigaction action;
action.sa_flags = SA_SIGINFO;
action.sa_sigaction = &sighand;
if (sigaction(SIGUSR2, &action, NULL) == -1) {
perror("sigusr: sigaction");
return 0;
}
printf("Signal handler installed, waiting for signal\n");
while(1) {sleep(2);}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
sigclient.c
int main(int argc, char *argv[])
{
union sigval value;
int pid = atoi(argv[1]);
value.sival_int = …Run Code Online (Sandbox Code Playgroud) 这是我的代码.它适用于C,但它的行为类似于C++中的结构.
#include<iostream>
using namespace std;
int main()
{
union myunion
{
int B;
double PI;
};
union myunion numbers;
numbers.PI = 3.14;
numbers.B = 12;
/* now storage of PI should be over-written */
cout<<numbers.PI<<endl;
cout<<numbers.B<<endl;
/* Output is 3.14 */
/* 12 */
/* Why it is behaving like Structures ? */
return 0;
}
Run Code Online (Sandbox Code Playgroud) void* GetData()
{
return reinterpret_cast<unsigned char*>(this);
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下是否会发生自动类型强制的情况?我怎么能将我的类的对象转换为unsigned char*?
我不知道如何破译这个男人有人需要告诉我发生了什么事请帮忙
typedef struct _ARGBCOLOR {
union {
struct {
BYTE B;
BYTE G;
BYTE R;
BYTE A;
};
DWORD ARGB;
};
} ARGBCOLOR, *PARGBCOLOR;
Run Code Online (Sandbox Code Playgroud) 我试图float从我从这里得到的十六进制表示创建一个.为表示32.50002,该站点将IEEE 754十六进制表示为0x42020005.
在我的代码中,我有这个:float f = 0x42020005;.但是,当我打印该值时,我得到的1.10E+9不是32.50002.为什么是这样?
我正在使用Microsoft Visual C++ 2010.
任何人都可以解释什么是C中的类型惩罚,并通过简单的示例程序演示何时出现此类问题?
我在许多网站(甚至维基)都进行了搜索,但即便如此,我也无法理解.