我已经学会了但并没有真正得到工会.我经历的每一个C或C++文本都会介绍它们(有时会传递),但是它们往往只提供很少的实际例子来说明为什么或在哪里使用它们.工会什么时候可以用于现代(甚至遗留)案件?我只有两个猜测是编程微处理器,当你的空间非常有限,或者你正在开发一个API(或类似的东西),并且你想迫使最终用户只有一个对象/类型的实例一度.这两个猜测是否接近正确?
我的印象是访问union除最后一个成员之外的成员是UB,但我似乎无法找到一个可靠的参考(除了声称它是UB但没有标准支持的答案).
那么,这是不确定的行为?
嘿,我正在寻找将用户输入的int转换为4个字节,我将其分配给字符数组.如何才能做到这一点?
例:
将用户输入175转换为
00000000 00000000 00000000 10101111
到目前为止所有答案的问题,转换255应该导致0 0 0 ff尽管它打印出来:0 0 0 ffffffff
unsigned int value = 255;
buffer[0] = (value >> 24) & 0xFF;
buffer[1] = (value >> 16) & 0xFF;
buffer[2] = (value >> 8) & 0xFF;
buffer[3] = value & 0xFF;
union {
unsigned int integer;
unsigned char byte[4];
} temp32bitint;
temp32bitint.integer = value;
buffer[8] = temp32bitint.byte[3];
buffer[9] = temp32bitint.byte[2];
buffer[10] = temp32bitint.byte[1];
buffer[11] = temp32bitint.byte[0];
Run Code Online (Sandbox Code Playgroud)
两者都导致0 0 0 ffffffff而不是0 …
C/C++中联合的大小是多少?它是最大数据类型的sizeof吗?如果是这样,如果联合的较小数据类型之一处于活动状态,编译器如何计算如何移动堆栈指针?
假设我有floatIEEE 754 binary32的保证.给定一个与存储的有效浮点相对应的位模式std::uint32_t,如何float以最有效的标准兼容方式将其重新解释为?
float reinterpret_as_float(std::uint32_t ui) {
return /* apply sorcery to ui */;
}
Run Code Online (Sandbox Code Playgroud)
我有几种方法,我知道/怀疑/假设有一些问题:
通过reinterpret_cast,
float reinterpret_as_float(std::uint32_t ui) {
return reinterpret_cast<float&>(ui);
}
Run Code Online (Sandbox Code Playgroud)
或者等价的
float reinterpret_as_float(std::uint32_t ui) {
return *reinterpret_cast<float*>(&ui);
}
Run Code Online (Sandbox Code Playgroud)
哪个遭受别名问题.
通过union,
float reinterpret_as_float(std::uint32_t ui) {
union {
std::uint32_t ui;
float f;
} u = {ui};
return u.f;
}
Run Code Online (Sandbox Code Playgroud)
这实际上并不合法,因为它只允许从最近写的成员读取.然而,似乎有些编译器(gcc)允许这样做.
通过std::memcpy,
float reinterpret_as_float(std::uint32_t ui) {
float f;
std::memcpy(&f, &ui, 4);
return f;
}
Run Code Online (Sandbox Code Playgroud)
哪种AFAIK是合法的,但复制单个单词的函数调用似乎很浪费,尽管它可能会被优化掉.
通过reinterpret_cast …
c++ standards-compliance type-conversion language-lawyer c++11
/* [1] */
int i = -1;
unsigned u = (unsigned)i;
/* [2] */
int i = -1;
unsigned u;
memcpy(&u, &i, sizeof i);
/* [3] */
int i = -1;
unsigned u = *(unsigned *)&i;
Run Code Online (Sandbox Code Playgroud)
为了将带符号的整数进行位复制到其未签名的伙伴,[1]应该可以在大多数机器上工作,但据我所知,这是不保证的行为.
[2] 应该做我想要的,但我想避免调用库函数的开销.
那怎么样[3]?它能有效地达到我想要的目的吗?
我正在使用Beej的网络指南,并遇到了一个别名问题.他提出了一个函数来返回特定结构的IPv4或IPv6地址:
1 void *get_in_addr( struct sockaddr *sa )
2 {
3 if (sa->sa_family == AF_INET)
4 return &(((struct sockaddr_in*)sa)->sin_addr);
5 else
6 return &(((struct sockaddr_in6*)sa)->sin6_addr);
7 }
Run Code Online (Sandbox Code Playgroud)
这会导致GCC 在第3行为sa吐出严格别名错误.据我所知,这是因为我这样调用这个函数:
struct sockaddr_storage their_addr;
...
inet_ntop(their_addr.ss_family,
get_in_addr((struct sockaddr *)&their_addr),
connection_name,
sizeof connection_name);
Run Code Online (Sandbox Code Playgroud)
我猜测别名与their_addr变量是类型的事实有关,sockaddr_storage而另一个不同类型的指针指向同一个内存.
就是要解决这个症结的最佳方式sockaddr_storage,sockaddr_in以及sockaddr_in6组成工会?看起来这应该是网络中的一个很好的领域,我只是找不到任何有最佳实践的好例子.
此外,如果有人能够准确解释别名问题发生的位置,我会非常感激.
我很好奇C++中类型惩罚指针/数组的约定.这是我目前的用例:
通过将其视为32位整数数组(我们知道它的总长度是4的倍数),然后将所有值相加并忽略溢出,计算二进制blob数据的简单32位校验和.
我希望这样的函数看起来像这样:
uint32_t compute_checksum(const char *data, size_t size)
{
const uint32_t *udata = /* ??? */;
uint32_t checksum = 0;
for (size_t i = 0; i != size / 4; ++i)
checksum += udata[i];
return udata;
}
Run Code Online (Sandbox Code Playgroud)
现在我的问题是,您认为转换data为"最佳"的方式是udata什么?
C风格演员?
udata = (const uint32_t *)data
Run Code Online (Sandbox Code Playgroud)
假设所有指针都是可转换的C++强制转换?
udata = reinterpret_cast<const uint32_t *>(data)
Run Code Online (Sandbox Code Playgroud)
C++在任意指针类型之间使用中间转换void*?
udata = static_cast<const uint32_t *>(static_cast<const void *>(data))
Run Code Online (Sandbox Code Playgroud)
通过工会铸造?
union {
const uint32_t *udata;
const char *cdata;
};
cdata = data;
// now …Run Code Online (Sandbox Code Playgroud) 我正在寻找一种合理有效的方法来确定浮点值(double)是否可以由整数数据类型(long,64位)精确表示.
我最初的想法是检查指数是否0(或更确切地说127).但这不会起作用,因为2.0e = 1 m = 1 ......
基本上,我被卡住了.我有一种感觉,我可以使用位掩码做到这一点,但我现在还没有理解如何做到这一点.
那么我怎样才能检查一个double是否完全可以表示为long?
谢谢
我从计算机系统:程序员的观点中了解到,IEEE标准要求使用以下64位二进制格式表示双精度浮点数:
+无穷大表示为具有以下模式的特殊值:
我认为double的完整64位应按以下顺序排列:
(一个或多个)(EXP)(FRAC)
所以我编写以下C代码来验证它:
//Check the infinity
double x1 = (double)0x7ff0000000000000; // This should be the +infinity
double x2 = (double)0x7ff0000000000001; // Note the extra ending 1, x2 should be NaN
printf("\nx1 = %f, x2 = %f sizeof(double) = %d", x1,x2, sizeof(x2));
if (x1 == x2)
printf("\nx1 == x2");
else
printf("\nx1 != x2");
Run Code Online (Sandbox Code Playgroud)
但结果是:
x1 = 9218868437227405300.000000, x2 = 9218868437227405300.000000 sizeof(double) = 8
x1 == x2
Run Code Online (Sandbox Code Playgroud)
为什么数字是有效数字而不是无穷大错误?
为什么x1 == …