相关疑难解决方法(0)

是&errno合法C?

每7.5,

[errno]扩展为具有int类型的可修改的lvalue175,其值由多个库函数设置为正错误号.未指定errno是宏还是使用外部链接声明的标识符.如果为了访问实际对象而禁止宏定义,或者程序定义名为errno的标识符,则行为未定义.

175)宏errno不必是对象的标识符.它可能会扩展为函数调用产生的可修改的左值(例如,*errno()).

我不清楚这是否足以要求&errno不是违反约束.C语言具有左值(例如寄存器存储类变量;但是这些变量只能是自动的,因此errno无法定义),&运算符是违反约束的.

如果&errno是合法的C,是否需要保持不变?

c errno language-lawyer

50
推荐指数
2
解决办法
2766
查看次数

numeric_limits <int> :: is_modulo在逻辑上是矛盾的吗?

另一个问题,主题std::numeric_limits<int>::is_modulo出现了.但我想的越多,看起来规格或GCC或两者都有问题.

让我先从一些代码开始:

#include <limits>
#include <iostream>

bool test(int x)
{
    return x+1 > x;
}

int main(int argc, char *argv[])
{
    int big = std::numeric_limits<int>::max();

    std::cout << std::numeric_limits<int>::is_modulo << " ";
    std::cout << big+1 << " ";
    std::cout << test(big) << "\n";
}
Run Code Online (Sandbox Code Playgroud)

当我用g++ -O3 -std=c++11(x86_64 GCC 4.7.2)编译它时,它产生以下输出:

1 -2147483648 1
Run Code Online (Sandbox Code Playgroud)

也就是说,is_modulo是的,一个加号INT_MAX是负数,一个加号INT_MAX大于INT_MAX.

如果你是那种有实际机会回答这个问题的人,你已经知道这里发生了什么.C++规范说整数溢出是Undefined Behavior; 允许编译器假设你不这样做; 因此争论x+1不可能INT_MAX; 因此编译器可能(并将会)编译test函数以true无条件地返回.到现在为止还挺好.

但是, …

c++ language-lawyer c++11

26
推荐指数
1
解决办法
584
查看次数

在C中表示负数?

C如何表示负整数?

它是通过二进制补码表示还是使用MSB(最重要的位)?

-1十六进制是ffffffff.

所以请为我澄清一下.

c negative-number twos-complement language-lawyer

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

什么时候在C++中改变一个值的位?

我有一个unsigned int实际存储有符号值的C++ .我想将此变量转换为a signed int,以便无符号和有符号值具有相同的二进制值.

unsigned int lUnsigned = 0x80000001;
int lSigned1 = (int)lUnsigned;                   // Does lSigned == 0x80000001?
int lSigned2 = static_cast<int>(lUnsigned);      // Does lSigned == 0x80000001?
int lSigned3 = reinterpret_cast<int>(lUnsigned); // Compiler didn't like this
Run Code Online (Sandbox Code Playgroud)

什么时候强制转换在C++中改变变量的位?例如,我知道从a int到a的转换float会改变位,因为它int是二进制补码并且float是浮点数.但其他场景呢?我不清楚C++中的规则.

在C99规范的6.3.1.3节中,它表示从无符号到有符号整数的转换是编译器定义的!

c++ casting

19
推荐指数
1
解决办法
5548
查看次数

在c ++中,从unsigned int到int的转换总是保留位模式吗?

从标准(4.7)看起来,当它们使用相同数量的位时,从int转换为unsigned int,纯粹是概念性的:

如果目标类型是无符号的,则结果值是与源整数一致的最小无符号整数(模2 n,其中n是用于表示无符号类型的位数).[注意:在二进制补码表示中,此转换是概念性的,并且位模式没有变化(如果没有截断). - 结束说明]

因此,在此方向上,转换会保留位掩码.我不确定标准是否保证从unsigned int到int的转换相同(同样,假设使用相同的位数).这里的标准说:

如果目标类型是有符号的,如果它可以在目标类型(和位域宽度)中表示,则该值不变; 否则,该值是实现定义的.

这究竟是什么意思"目的地类型"?例如,2 ^ 32-1不能用32位int表示.这是否意味着它无法在目标类型中表示,因此不能假设位模式保持不变?

c++ casting language-lawyer

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

如何在不调用un或实现定义的行为的情况下从uint8_t的缓冲区中读取有符号整数?

这是一个简单的函数,试图从big-endian缓冲区读取一个通用的二进制补码整数,我们假设std::is_signed_v<INT_T>:

template<typename INT_T>
INT_T read_big_endian(uint8_t const *data) {
    INT_T result = 0;
    for (size_t i = 0; i < sizeof(INT_T); i++) {
        result <<= 8;
        result |= *data;
        data++;
    }
    return result;
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,这是未定义的行为,因为最后一个<<=转移到符号位.


所以现在我们尝试以下方法:

template<typename INT_T>
INT_T read_big_endian(uint8_t const *data) {
    std::make_unsigned_t<INT_T> result = 0;
    for (size_t i = 0; i < sizeof(INT_T); i++) {
        result <<= 8;
        result |= *data;
        data++;
    }
    return static_cast<INT_T>(result);
}
Run Code Online (Sandbox Code Playgroud)

但我们现在正在调用实现定义的行为static_cast,从unsigned转换为signed.


如何在"明确定义"的领域中做到这一点?

c++ undefined-behavior implementation-defined-behavior

7
推荐指数
1
解决办法
166
查看次数

如何处理通用代码中可能混合的有符号和无符号算术?

混合有符号和无符号算术的典型示例似乎是:

\n
    unsigned int u = 10;\n    int          a = -42;\n    auto tmp1 = u - a;\n    std::cout << tmp1 << std::endl;\n    int tmp2 = tmp1;\n    std::cout << tmp2 << std::endl;\n
Run Code Online (Sandbox Code Playgroud)\n

(请注意,我使用的是auto tmp1这样我可以显示中间结果并检查类型。当然,在实际代码中,这都是一行)

\n

如果你启用足够多的警告(-Wconversion在 clang-13 上,另外,-Wsign-conversion在 gcc-11 上),编译器会很好地抱怨:

\n
main.cpp:148:21: warning: conversion to \xe2\x80\x98unsigned int\xe2\x80\x99 from \xe2\x80\x98int\xe2\x80\x99 may change the sign of the result [-Wsign-conversion]\n  148 |     auto tmp1 = u - a;\n      |                     ^\nmain.cpp:150:16: warning: conversion to \xe2\x80\x98int\xe2\x80\x99 from \xe2\x80\x98unsigned int\xe2\x80\x99 …
Run Code Online (Sandbox Code Playgroud)

c++ unsigned signed

5
推荐指数
0
解决办法
380
查看次数

将char类型(不是ascii)转换为int

我想将char类型转换为int类型而不会丢失签名的含义,所以我在文件int_test.c中编写代码并且它有效:

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>

#define c2int(x) \
({                         \
        int t;             \
        if (x > 0x80)      \
                t = x | (1 << sizeof(int) * 8) - (1 << sizeof(char) * 8); \
        else               \
                t = x;     \
        t;                 \
 })

int main()
{
        uint8_t a = 0xFE;
        int b;

        b = c2int(a);

        printf("(signed char)a = %hhi, b = %d\n", a, b);

        exit(EXIT_SUCCESS);
}
Run Code Online (Sandbox Code Playgroud)

运行结果是:

(signed char)a = -2,b = -2

编译日志是:

gcc -o int_test int_test.c …

c type-conversion

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