我想定义一个带有unsigned intas参数的函数,并向参数返回一个int全等模UINT_MAX + 1.
第一次尝试可能如下所示:
int unsigned_to_signed(unsigned n)
{
return static_cast<int>(n);
}
Run Code Online (Sandbox Code Playgroud)
但正如任何语言律师所知,从无符号转换为大于INT_MAX的已签名值是实现定义的.
我想实现这一点,以便(a)它只依赖于规范规定的行为; (b)它在任何现代机器上编译成无操作并优化编译器.
对于奇怪的机器......如果没有签名的int congruent将UINT_MAX + 1模数为unsigned int,那么假设我想抛出一个异常.如果有多个(我不确定这是否可能),那么就说我想要最大的一个.
好的,第二次尝试:
int unsigned_to_signed(unsigned n)
{
int int_n = static_cast<int>(n);
if (n == static_cast<unsigned>(int_n))
return int_n;
// else do something long and complicated
}
Run Code Online (Sandbox Code Playgroud)
当我不是一个典型的二元补充系统时,我并不太关心效率,因为我认为不太可能.如果我的代码成为2050年无所不在的符号量级系统的瓶颈,那么,我敢打赌,有人可以解决这个问题并对其进行优化.
现在,第二次尝试非常接近我想要的.尽管转换int为某些输入的实现定义,但是unsigned标准保证转换为保留模UINT_MAX + 1的值.所以条件确实检查我想要什么,它将在我可能遇到的任何系统上编译成什么.
但是......我仍然在int没有首先检查它是否会调用实现定义的行为.在2050年的一些假设系统中,它可以做谁知道什么.所以我想说我想避免这种情况.
问题:我的"第三次尝试"应该是什么样的?
回顾一下,我想:
[更新]
让我举一个例子来说明为什么这不是一个微不足道的问题.
考虑具有以下属性的假设C++实现:
sizeof(int) 等于4sizeof(unsigned) 等于4INT_MAX 等于32767INT_MIN等于-2 …定义函数的两个条件pure如下:
如果第一个条件始终为真,那么是否有第二次条件不为真?
即真的只有第一个条件才需要吗?
javascript functional-programming language-lawyer pure-function
假设我去编译一些编写不佳的C ++源代码,这些源代码会调用未定义的行为,因此(正如他们所说)“任何事情都可能发生”。
从C ++语言规范在“合格”编译器中认为可接受的角度来看,这种情况下的“任何情况”是否包括编译器崩溃(或窃取我的密码,或者在编译时出现异常或错误),或者未定义行为的范围专门限于生成的可执行文件运行时会发生什么?
这个(注意逗号运算符):
#include <iostream>
int main() {
int x;
x = 2, 3;
std::cout << x << "\n";
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出2.
但是,如果您使用return逗号运算符,则:
#include <iostream>
int f() { return 2, 3; }
int main() {
int x;
x = f();
std::cout << x << "\n";
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出3.
为什么逗号运算符的行为与return?
c++ return operator-precedence comma-operator language-lawyer
(参考这个问题和答案.)
在C++ 17标准之前,[basic.compound]/3中包含以下句子:
如果类型T的对象位于地址A,则类型为cv T*的指针(其值为地址A)被称为指向该对象,而不管该值是如何获得的.
但是自从C++ 17以来,这句话已被删除.
例如,我相信这句话使这个示例代码定义,并且从C++ 17开始这是未定义的行为:
alignas(int) unsigned char buffer[2*sizeof(int)];
auto p1=new(buffer) int{};
auto p2=new(p1+1) int{};
*(p1+1)=10;
Run Code Online (Sandbox Code Playgroud)
在C++ 17之前,p1+1保持地址*p2并具有正确的类型,因此*(p1+1)是指向*p2.在C++中,17 p1+1是一个指向前端的指针,所以它不是指向对象的指针,我相信它不是可以解除引用的.
对标准权的这种修改的解释是否还有其他规则来补偿所引用的句子的删除?
调用未定义行为的代码(在此示例中,除以零)将永远不会执行,程序是否仍未定义行为?
int main(void)
{
int i;
if(0)
{
i = 1/0;
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我认为它仍然是未定义的行为,但我在标准中找不到支持或否认我的任何证据.
那么,有什么想法吗?
考虑以下简短的C++程序:
#include <iostream>
class B {
public:
operator bool() const {
return false;
}
};
class B2 : public B {
public:
operator int() {
return 5;
}
};
int main() {
B2 b;
std::cout << std::boolalpha << (bool)b << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
如果我在不同的编译器上编译它,我会得到各种结果.使用Clang 3.4和GCC 4.4.7打印true,而Visual Studio 2013打印false,这意味着它们调用不同的强制转换操作符(bool)b.根据标准,这是正确的行为?
在我的理解operator bool()需要转变,而operator int()将需要int向bool转换,所以编译器应该选择第一个.是否const做一些与该是由编译器认为更"贵"常量转换?
如果我删除了const,所有编译器同样产生false输出.另一方面,如果我将两个类组合在一起(两个运算符将在同一个类中),则所有三个编译器都将生成true输出.
今天我遇到了问题.我需要一个static会员功能,const不是必须而是更好.但是,我没有成功.任何人都可以说为什么或如何?
如果我输入019 > 020JavaScript控制台(在Chrome和Firefox中测试),我会得到答案true.
这是因为020被解释为OctalIntegerLiteral(等于16),而019显然被解释为DecimalLiteral(和等于19).由于19是大于16,019 > 020是true.
令我困惑的是为什么019被解释为DecimalLiteral第一名.它是哪种产品?DecimalIntegerLiteral不允许019:
DecimalIntegerLiteral ::
0
NonZeroDigit DecimalDigits_opt
Run Code Online (Sandbox Code Playgroud)
OctalIntegerLiteral也不允许019(因为9不是八进制数字):
OctalIntegerLiteral ::
0 OctalDigit
OctalIntegerLiteral OctalDigit
OctalDigit :: one of
0 1 2 3 4 5 6 7
Run Code Online (Sandbox Code Playgroud)
因此,从我在规范中看到的,019实际应该被拒绝,我不明白为什么它被解释为十进制整数.
我想这里有一些兼容性规则,但我找不到正式的定义.可以请任何人帮我这个吗?
(为什么我需要这个:我正在使用JavaCC为Java开发一个JavaScript/ECMAScript解析器,并且必须特别注意规范 - 以及它的偏差.)
有一个旧帖子要求一个sizeof可以返回的构造0.高信誉用户有一些高分答案说,按标准,没有类型或变量可以有0的大小.我同意100%.
然而,这个新的答案提出了这个解决方案:
struct ZeroMemory {
int *a[0];
};
Run Code Online (Sandbox Code Playgroud)
我正要进行投票和评论,但是在这里度过的时间教会我检查我100%肯定的事情.所以...让我惊讶的是,gcc并clang显示出相同的结果:sizeof(ZeroMemory) == 0.更重要的是,变量的大小是0:
ZeroMemory z{};
static_assert(sizeof(z) == 0); // Awkward...
Run Code Online (Sandbox Code Playgroud)
Whaaaat ...?
这怎么可能?
language-lawyer ×10
c++ ×7
javascript ×2
c ×1
c++14 ×1
c++17 ×1
casting ×1
const-method ×1
ecmascript-5 ×1
grammar ×1
integer ×1
javacc ×1
pointers ×1
return ×1
sizeof ×1
static ×1