我已经学会了但并没有真正得到工会.我经历的每一个C或C++文本都会介绍它们(有时会传递),但是它们往往只提供很少的实际例子来说明为什么或在哪里使用它们.工会什么时候可以用于现代(甚至遗留)案件?我只有两个猜测是编程微处理器,当你的空间非常有限,或者你正在开发一个API(或类似的东西),并且你想迫使最终用户只有一个对象/类型的实例一度.这两个猜测是否接近正确?
namespace WTF {
/*
* C++'s idea of a reinterpret_cast lacks sufficient cojones.
*/
template<typename TO, typename FROM>
TO bitwise_cast(FROM in)
{
COMPILE_ASSERT(sizeof(TO) == sizeof(FROM), WTF_wtf_reinterpret_cast_sizeof_types_is_equal);
union {
FROM from;
TO to;
} u;
u.from = in;
return u.to;
}
} // namespace WTF
Run Code Online (Sandbox Code Playgroud)
这是否意味着我的意思?可能是这样,bitwise_cast如果POD中的任何一个TO或FROM不是POD并且不是(AFAIK)比内置的C++更强大,那么这里指定的实现将不会编译reinterpret_cast.
我在这里看到的唯一亮点就是没有人似乎bitwise_cast在Chromium项目中使用.
在gcc-strict-aliasing-and-casting-through-a-union中,我问是否有人遇到过通过指针进行联合惩罚的问题.到目前为止,答案似乎是否定的.
这个问题是广泛的:你有任何关于gcc和严格走样恐怖故事?
背景:引用AndreyT在c99-strict-aliasing-rules-in-c-gcc中的答案:
"严格的别名规则植根于自[标准化]时代开始以来C和C++中存在的标准部分.禁止通过另一种类型的左值访问一种类型的对象的条款存在于C89/90中(6.3 )以及C++ 98(3.10/15)......并非所有编译器都希望(或敢于)强制执行或依赖它.
好吧,gcc现在敢于用它的-fstrict-aliasing开关来做到这一点.这引起了一些问题.例如,请参阅有关Mysql错误的优秀文章 http://davmac.wordpress.com/2009/10/,以及http://cellperformance.beyond3d.com/articles/2006/06/understanding中同样出色的讨论.-strict-aliasing.html.
其他一些不太相关的链接:
重复一遍,你有自己的恐怖故事吗?当然,没有表示的问题-Wstrict-aliasing是优选的.其他C编译器也很受欢迎.
6月2日补充:迈克尔伯尔的答案中的第一个链接,确实有资格作为恐怖故事,可能有点过时(从2003年开始).我做了一个快速测试,但问题显然已经消失了.
资源:
#include <string.h>
struct iw_event { /* dummy! */
int len;
};
char *iwe_stream_add_event(
char *stream, /* Stream of events */
char *ends, /* End of stream */
struct iw_event *iwe, /* Payload */
int event_len) /* Real size of payload …Run Code Online (Sandbox Code Playgroud) 鉴于代码:
struct s1 {unsigned short x;};
struct s2 {unsigned short x;};
union s1s2 { struct s1 v1; struct s2 v2; };
static int read_s1x(struct s1 *p) { return p->x; }
static void write_s2x(struct s2 *p, int v) { p->x=v;}
int test(union s1s2 *p1, union s1s2 *p2, union s1s2 *p3)
{
if (read_s1x(&p1->v1))
{
unsigned short temp;
temp = p3->v1.x;
p3->v2.x = temp;
write_s2x(&p2->v2,1234);
temp = p3->v2.x;
p3->v1.x = temp;
}
return read_s1x(&p1->v1);
}
int test2(int x)
{
union s1s2 q[2]; …Run Code Online (Sandbox Code Playgroud) 我将我的问题总结为以下简短程序.
它仅在-O3模式下导致SEGFAULT(-O2工作正常).根据gdb它发生*f = 0在线.
#include <iostream>
void func1(int s, int t)
{
char* buffer = new char[s + t*sizeof(float)];
if (!buffer)
{
std::cout << "new failed\n";
return;
}
float* f = (float*)(buffer + s);
for (int i = 0; i < t; ++i)
{
*f = 0;
//std::cout << i << std::endl; // if uncomment this line everything will work fine
++f;
}
delete [] buffer;
std::cout << "done\n";
}
int main()
{
int s = …Run Code Online (Sandbox Code Playgroud) 我不确定代码是否在断言转换中具有指针别名(或其他标准一致性问题).似乎指向联合类型的指针应该能够转换为第一个成员的指针,因为联合只由这两个结构组成,我认为对第一个成员的强制转换应该有效,但我不是确定这是否正确,或者我是否在过程中掩盖了填充细节.工会是否需要填补高位?
似乎这是未指明的行为?有没有人知道这是否被支持.我知道有一种替代的标准方法可以通过使用带有enum type字段和struct container_storage成员的结构来实现这一点,但考虑到此信息已经存在,这似乎是浪费空间struct contained
linux中的编译命令:gcc -std=c99 -Wextra -pedantic -fstrict-aliasing test.c && ./a.out && echo $?返回0
#include <stdlib.h>
#include <assert.h>
enum type {type_a = 1, type_b = 2};
struct contained {
int some_other_field;
enum type type;
};
struct container_a {
struct contained contained;
int test;
};
struct container_b {
struct contained contained;
char test;
};
union container_storage {
struct container_a container_a;
struct container_b container_b;
};
int
main(int argc, char **argv)
{
union …Run Code Online (Sandbox Code Playgroud) 此问题与Rcpp条件中的NA值相关联.
我基本上有一些循环在多个(双)元素上的Rcpp代码.我需要检查每个元素是否缺少值(我不能使用矢量化).让我们计算一个向量中缺失值的数量,就像最小可重现的例子一样:
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
int nb_na(const NumericVector& x) {
int n = x.size();
int c = 0;
for (int i = 0; i < n; i++) if (R_IsNA(x[i])) c++;
return c;
}
// [[Rcpp::export]]
int nb_na3(const NumericVector& x) {
int n = x.size();
int c = 0;
for (int i = 0; i < n; i++) if (x[i] == 3) c++;
return c;
}
// [[Rcpp::export]]
LogicalVector na_real(NumericVector x) {
return x == …Run Code Online (Sandbox Code Playgroud) 我需要将"void*"转换为int,但编译器会一直给我警告.不知道是否有办法改变代码,以便编译器不会抱怨.这在代码库中发生了很多,特别是在传递参数以启动新线程时.
$ g++ -fpermissive te1.cc
te1.cc: In function ‘void dummy(void*)’:
te1.cc:4:15: warning: cast from ‘void*’ to ‘int’ loses precision [-fpermissive]
int x = (int)p;
^
Run Code Online (Sandbox Code Playgroud)
这是简单的代码"te1.cc":
#include <stdio.h>
extern void someFunc(int);
void dummy(int type, void *p) {
if (type == 0) {
int x = (int)p;
someFunc(x);
} else if (type == 1) {
printf("%s\n", (char*)p);
}
}
int main(int argc, char *argv[]) {
void *p = (void*)5;
dummy(p);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
UDPATE1
我明白我会失去精确度.它有时是有意的.我需要的是有办法在我知道的地方删除警告,确保它是安全的.很抱歉没有在之前说清楚.
UDPATE2
更新了代码片段,以便说明这一点不那么重要.该参数需要传递不同类型的值.我需要一种方法来施放而不产生警告.