小编Sha*_*our的帖子

工会和打字

我一直在寻找,但找不到明确的答案.

很多人说使用工会来打字 - 双关语是不明确的和不好的做法.为什么是这样?考虑到你写入原始信息的内存并不仅仅是自己的改变,我看不出为什么它会做任何未定义的任何原因(除非它超出了堆栈的范围,但这不是一个联合问题,这将是糟糕的设计).

人们引用严格的别名规则,但在我看来,就像说你不能这样做,因为你做不到.

如果不打双关语,联盟的意义又是什么呢?我在某个地方看到它们应该被用来在不同的时间使用相同的内存位置来获取不同的信息,但为什么不在再次使用之前删除信息呢?

总结一下:

  1. 为什么使用工会进行打字是不好的?
  2. 如果不是这样,他们的意义何在?

额外信息:我主要使用的是C++,但想了解它和C.特别是我正在使用工会在浮点数和原始十六进制之间进行转换以通过CAN总线发送.

c c++ unions type-punning

63
推荐指数
4
解决办法
1万
查看次数

在C++ 14中,C++标准是否在使用不确定值和未定义行为方面发生了变化?

正如初始化所述,需要进行左值到右值的转换?是int x = x;UB吗?C++标准在3.3.2 声明部分中有一个令人惊讶的例子,其中a int用它自己的不确定值初始化:

int x = 12;
{ int x = x; }
Run Code Online (Sandbox Code Playgroud)

这里第二个x用它自己的(不确定的)值初始化.- 结束例子 ]

Johannes对此问题的回答表明是未定义的行为,因为它需要左值到右值的转换.

在最新的C++ 14草案标准中N3936,可以在此处找到此示例已更改为:

unsigned char x = 12;
{ unsigned char x = x; }
Run Code Online (Sandbox Code Playgroud)

这里第二个x用它自己的(不确定的)值初始化.- 结束例子 ]

C++ 14中有关于不确定值和未定义行为的变化,这些变化在示例中引发了这种变化吗?

c++ undefined-behavior language-lawyer c++11 c++14

62
推荐指数
1
解决办法
3991
查看次数

为什么表达式而不是常量,在C for循环的条件中?

在许多编程比赛中,我看到有人写这种类型的for-loop

for(i = 0; i < (1 << 7); i++)
Run Code Online (Sandbox Code Playgroud)

除非我遗漏了什么,否则就是这样

for(i = 0; i < 128; i++)
Run Code Online (Sandbox Code Playgroud)

为何使用该(1 << 7)版本?
每次不必要的开销是不是计算条件?

c expression for-loop coding-style constantfolding

57
推荐指数
5
解决办法
3909
查看次数

删除了默认构造函数.仍然可以创建对象......有时候

c ++ 11统一初始化语法的天真,乐观和哦......错误的观点

我认为,因为C++ 11用户定义的类型对象应该使用新{...}语法而不是旧(...)语法构造(除了构造函数重载std::initializer_list和类似参数(例如std::vector:size ctor vs 1 elem init_list ctor)).

好处是:没有狭义的隐式转换,最烦人的解析没有问题,一致性(?).我没有看到任何问题,因为我认为它们是相同的(除了给出的例子).

但他们不是.

一个纯粹疯狂的故事

{}调用默认的构造函数.

......除非:

  • 删除默认构造函数
  • 没有定义其他构造函数.

然后它看起来像是值而不是初始化对象?...即使对象已经删除了默认构造函数,{}也可以创建一个对象.这不是打败了删除的构造函数的全部目的吗?

......除非:

  • 该对象有一个删除的默认构造函数和
  • 其他构造函数定义.

然后失败了call to deleted constructor.

......除非:

  • 该对象有一个删除的构造函数和
  • 没有其他构造函数定义和
  • 至少是一个非静态数据成员.

然后失败并丢失了字段初始值设定项.

但是,您可以使用它{value}来构造对象.

好吧也许这与第一个异常相同(值init对象)

......除非:

  • 该类有一个删除的构造函数
  • 并且至少有一个数据成员默认初始化.

然后也{}不能{value}创建一个对象.

我相信我错过了一些.具有讽刺意味的是,它被称为统一初始化语法.我再说一遍:UNIFORM初始化语法.

这种疯狂是什么?

情景A.

删除默认构造函数:

struct foo {
  foo() = delete;
};

// All bellow OK (no errors, no warnings) …
Run Code Online (Sandbox Code Playgroud)

c++ language-lawyer aggregate-initialization list-initialization c++14

49
推荐指数
3
解决办法
6977
查看次数

浮点除零的行为

考虑

#include <iostream>
int main()
{
    double a = 1.0 / 0;
    double b = -1.0 / 0;
    double c = 0.0 / 0;
    std::cout << a << b << c; // to stop compilers from optimising out the code.    
}
Run Code Online (Sandbox Code Playgroud)

我一直认为这a将是+ Inf,b将是-Inf,并且c将是NaN.但我也听到传言说严格来说浮点除零的行为是未定义的,因此上面的代码不能被认为是可移植的C++.(理论上,这会消除我的百万行加上代码堆栈的完整性.糟糕.)

谁是对的?

注意我对实现定义感到满意,但我在谈论吃猫,在这里恶魔打喷嚏的未定义行为.

c++ floating-point divide-by-zero undefined-behavior language-lawyer

48
推荐指数
5
解决办法
1万
查看次数

C++预处理器中R和L有什么特别之处?

我通过Visual Studio 2013预处理器运行以下代码.输出令我惊讶.

hello.cpp的内容:

#define A(j) #j

A(A?)
A(B?)
A(C?)
A(D?)
A(E?)
A(F?)
A(G?)
A(H?)
A(I?)
A(J?)
A(K?)
A(L?)
A(M?)
A(N?)
A(O?)
A(P?)
A(Q?)
A(R?)
A(S?)
A(T?)
A(U?)
A(V?)
A(W?)
A(X?)
A(Y?)
A(Z?)
Run Code Online (Sandbox Code Playgroud)

命令:

cl /P hello.cpp
Run Code Online (Sandbox Code Playgroud)

hello.i包含:

#line 1 "hello.cpp"



"A?"
"B?"
"C?"
"D?"
"E?"
"F?"
"G?"
"H?"
"I?"
"J?"
"K?"
"L"
"M?"
"N?"
"O?"
"P?"
"Q?"
"R"
"S?"
"T?"
"U?"
"V?"
"W?"
"X?"
"Y?"
"Z?"
Run Code Online (Sandbox Code Playgroud)

我试着打电话给A(L?p:q)时碰到了这个,这导致了"Lp:q",这对我不利.

这是正确的,定义明确的C++吗?C++中的L和R有什么特别之处?如果文件具有.c扩展名,则L和R被视为与字母表的其余部分相同.这与C++ 11有关吗?它必须是一个新功能,因为旧版本的MSVS不会以特殊方式使用L和R.

我能做些什么来阻止MSVS 2013以这种特殊方式治疗L和R?

c++ visual-c++ compiler-bug c-preprocessor c++11

47
推荐指数
1
解决办法
1888
查看次数

为什么常量表达式会排除未定义的行为?

我正在研究核心常量表达式*中允许的内容,这在C++标准草案的5.19 常量表达式2段中有所描述:

条件表达式是核心常量表达式,除非它涉及以下之一作为潜在评估的子表达式(3.2),但是未评估的逻辑AND(5.14),逻辑OR(5.15)和条件(5.16)操作的子表达式不考虑[注意:重载的运算符调用函数.-end note]:

并列出随后的子弹中的排除项并包括(强调我的):

- 具有未定义行为的操作 [注意:包括,例如,有符号整数溢出(第5条),某些指针算术(5.7),除零(5.6)或某些移位操作(5.8) - 结束注释];

?为什么常量表达式需要此子句来涵盖未定义的行为常量表达式是否有一些特殊的东西需要未定义的行为才能在排除中进行特殊划分?

拥有这个条款是否给了我们没有它的任何优势或工具?

作为参考,这看起来像广义常量表达式提案的最新修订版.

c++ sfinae undefined-behavior constexpr c++11

46
推荐指数
3
解决办法
2752
查看次数

在C++ 14中,在新表达式的维度中使用double是否有效?

在C++ 14中给出以下代码:

void foo() {
  double d = 5.0;
  auto p1 = new int[d];
}
Run Code Online (Sandbox Code Playgroud)

clang在没有诊断的情况下编译它,而另一方面gcc产生以下诊断(见它在godbolt中生活):

error: expression in new-declarator must have integral or enumeration type
    7 |     auto p1 = new int[d];
      |                       ^
Run Code Online (Sandbox Code Playgroud)

我特意标记了这个C++ 14,因为在C++ 11模式下,clang将其视为格式不正确并产生以下诊断(请参阅godbolt中的内容):

error: array size expression must have integral or unscoped enumeration type, not 'double'
    auto p1 = new int[d];
              ^       ~
Run Code Online (Sandbox Code Playgroud)

clang是否正确?如果是这样,在C++ 14中有什么改变允许这个?

c++ language-lawyer c++14 new-expression

42
推荐指数
1
解决办法
2191
查看次数

如何使用初始化列表创建std :: array而不直接提供大小

我怎样才能a3编译?

int main()
{
    int a1[] = { 1, 2, 3 };
    std::array<int, 3> a2 = { 1, 2, 3 };
    std::array<int> a3 = { 1, 2, 3 };
}
Run Code Online (Sandbox Code Playgroud)

使用初始化列表时,对数组的大小进行硬编码是非常不方便的,也是很脆弱的,特别是长的列表.有什么工作吗?我希望如此,否则我很失望,因为我讨厌C阵列,std::array应该是他们的替代品.

c++ initialization stdarray

39
推荐指数
2
解决办法
2万
查看次数

C++ 11成员初始化列表与类内初始化程序?

在C++ 11中初始化对象成员变量的这些方法有何不同?还有另外一种方法吗?哪种方式更好(性能)?:

class any {
  public:
    obj s = obj("value");
    any(){}
};
Run Code Online (Sandbox Code Playgroud)

要么

class any {
  public:
    obj s;
    any(): s("value"){}
};
Run Code Online (Sandbox Code Playgroud)

谢谢.

c++ initialization c++11

38
推荐指数
3
解决办法
1万
查看次数