小编Öö *_*iib的帖子

为什么从char转换为std :: byte可能是未定义的行为?

所述std::byte的C++ 17需要为枚举类:

enum class byte : unsigned char {};
Run Code Online (Sandbox Code Playgroud)

我们可能希望使用它std::byte来表示原始内存而不是chars中的一个,因为它更安全类型,定义了特定于字节的运算符,并且不能intchars那样提升为蓝色.我们需要使用显式强制转换或to_integer转换std::byte为其他整数.然而,从很多来源我们仍然得到char(或更可能是整个缓冲区char),因此可能想要转换它:

void fn(char c)
{
    std::byte b = static_cast<std::byte>(c);
    // ... that may invoke undefined behavior, read below
}
Run Code Online (Sandbox Code Playgroud)

可能char是实现定义的签名.因此,上面的负值可能超出范围.std::numeric_limits<char>::is_signedtruecunsigned char

现在在8.2.9 Static cast [expr.static.cast]第10段的C++ 17标准中,我们可以读到:

可以将整数或枚举类型的值显式转换为完整的枚举类型.如果原始值在枚举值(10.2)的范围内,则该值不变.否则,行为未定义.

从10.2我们可以看出,所提到的范围是基础类型的范围.因此,为了避免未定义的行为,我们必须编写更多代码.例如,我们可以添加一个强制转换unsigned char来实现在强制转换期间模块化算术的定义效果:

void fn(char c)
{
    std::byte b = static_cast<std::byte>(static_cast<unsigned char>(c));
    // ... now we have done it …
Run Code Online (Sandbox Code Playgroud)

c++ language-lawyer

21
推荐指数
1
解决办法
553
查看次数

难以衡量C/C++性能

我写了一段C代码,以展示关于优化和分支预测的讨论中的一点.然后我注意到比我预期的更多样化的结果.我的目标是用C++和C之间通用子集的语言编写它,这对于两种语言都是标准兼容的并且相当便携.它在不同的Windows PC上进行了测试:

#include <stdio.h>
#include <time.h>

/// @return - time difference between start and stop in milliseconds
int ms_elapsed( clock_t start, clock_t stop )
{
    return (int)( 1000.0 * ( stop - start ) / CLOCKS_PER_SEC );
}

int const Billion = 1000000000;
/// & with numbers up to Billion gives 0, 0, 2, 2 repeating pattern 
int const Pattern_0_0_2_2 = 0x40000002; 

/// @return - half of Billion  
int unpredictableIfs()
{
    int sum = 0;
    for ( int i = …
Run Code Online (Sandbox Code Playgroud)

c c++ optimization performance measurement

12
推荐指数
1
解决办法
1945
查看次数

对于 C++ 重载解析,为什么 {} 是 int 比 string 更好?

重载解析倾向于将 {} 视为某种基本类型,而不是某种容器。

例如:

#include <iostream>
#include <string>

void foo(const std::string&) {std::cout << "string\n";}
void foo(int) {std::cout << "int\n";}

int main() { foo({}); }
Run Code Online (Sandbox Code Playgroud)

编译时无需任何诊断和输出:

整数

https://godbolt.org/z/zETfrs5as

如果注释掉重载int,那么它可以很好地与string.

问题是为什么?从程序员的角度来看,这可能是令人困惑的错觉。

c++ language-lawyer

9
推荐指数
1
解决办法
176
查看次数

std :: map是否分配了它的比较器?

std::map拷贝赋值(风格map1 = map2;)需要复制的比较map2map1

我已经测试了实际的实现.我更感兴趣的是它在C++标准中的位置.

c++ dictionary assignment-operator language-lawyer

8
推荐指数
1
解决办法
165
查看次数

提升精神将整个比赛作为一个字符串

我正在尝试使用boost精神框架来定义自己的语法,并且我正在定义这样的匹配规则:

value = (
        char_('"') >>
        (*qi::lexeme[
                char_('\\') >> char_('\\') |
                char_('\\') >> char_('"')  |
                graph - char_('"') |
                char_(' ')
        ])[some_func] >>
        char_('"')
);
Run Code Online (Sandbox Code Playgroud)

我想将一个动作 - some_func - 分配到它的一部分,并将整个匹配的字符串作为参数传递.但不幸的是,我会得到类似的东西vector<boost::variant<boost::fusion::vector2 ..a lot of stuff...)...>.我可以以某种方式将整个数据作为char*,std :: string甚至void*与大小?

c++ boost boost-spirit boost-spirit-qi

6
推荐指数
1
解决办法
2096
查看次数

如何在constexpr函数中使用临时变量?

这是我想要做的简化版本.

constexpr float f(float a, float b){
    constexpr float temp = a+b;
    return temp*temp*temp;
}
Run Code Online (Sandbox Code Playgroud)

在我的版本中,a + b更复杂,所以我不想剪切和粘贴三次.使用3*(a + b)也不是实际功能的有效解决方案.我试图保持与语法相关的问题,而不是代数.我可以通过将+ b移动到它自己的constexpr函数来实现它,但我宁愿不用其他无用的函数来污染命名空间.

c++ constexpr

5
推荐指数
2
解决办法
856
查看次数

两个签名号码之间的距离

两个数字之间的距离通常计算如下:

long distance(long x, long y)
{
     return x > y ? x - y : y - x;
}
Run Code Online (Sandbox Code Playgroud)

但是对于带符号xy这些减法,可能会溢出,因此该函数可以在C和C++中调用未定义的行为.

解决该问题的一种方法是使用无符号类型来表示结果距离.距离不能为负数,因此不需要签名类型.有符号类型的最小值和最大值之间的距离应该适合相同大小的无符号类型.(编辑:正如chux回答的那样,假设并不完全正确.)所以我确实修改了第一个函数:

unsigned long distance(long x, long y)
{
    return (x > y) ? (unsigned long)x - (unsigned long)y
                   : (unsigned long)y - (unsigned long)x;
}
Run Code Online (Sandbox Code Playgroud)

它现在是否以标准符合和便携方式正确计算两个有符号长度之间的距离?如果没有,那将是什么修复?

c c++ distance language-lawyer

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