简体   繁体   English

在 { } | 内缩小从 int 到 char 的转换 char 的签名问题

[英]Narrowing Conversion from int to char inside { } | An issue with signedness of char

See the behaviour of char in case of a vector<char> and a standalone char :vector<char>和独立char的情况下查看char的行为:

#include <iostream>
#include <vector>

using namespace std;

int main()
{
    vector<int> someInts = {2, 3, 1 + 5};
    // I can perform operations   ^^^^^   inside the braces in this case

    // vector<char> someChars = {'a', 'b', 'r' + 'z'};
    // But doing the same in case of char  ^^^^^^^^^  gives an error

    // However, it works for a standalone char
    char ch = 'r' + 'z';
    cout << ch;
    // Value^^^is '∞' as expected
}

Uncommenting the vector<char> line gives:取消对vector<char>行的注释给出:

Error: narrowing conversion of '236' from 'int' to 'char' inside { }错误:在 {} 中缩小从 'int' 到 'char' 的 '236' 转换

This was the problem.这就是问题所在。


Then I read this documentation of List Initialization , and saw the following which might be related to this problem:然后我阅读 List Initialization的文档,并看到了以下可能与此问题有关的内容:

Narrowing conversions缩小转化范围

list-initialization limits the allowed implicit conversions by prohibiting the following: list-initialization 通过禁止以下内容来限制允许的隐式转换:

  • many other reasons许多其他原因
  • conversion from integer or unscoped enumeration type to integer type that cannot represent all values of the original, except where source is a constant expression whose value can be stored exactly in the target type从 integer 或无作用域枚举类型到 integer 类型的转换,它不能表示原始的所有值,除非 source 是一个常量表达式,其值可以完全存储在目标类型中

It made me understand the error message (I guess), and I changed vector<char> to vector<unsigned char> and it worked:它让我理解了错误消息(我猜),我将vector<char>更改为vector<unsigned char>并且它起作用了:

vector<unsigned char> someChars = {'a', 'b', 'r' + 'z'};
for (char ch : someChars)
    cout << '_' << ch;

Output: _a_b_∞ Output: _a_b_∞


So, my question is:所以,我的问题是:

  1. If signedness of char was the problem, how did the standalone version of char work in that case?如果char的签名是问题,那么在这种情况下,独立版本的charchar工作的? With reference to this thread on stackoverflow, how did the same compiler choose signed char for vector<char> and unsigned char for char ?参考 stackoverflow 上的这个线程,同一个编译器是如何为vector<char>选择signed char和为char选择unsigned char的?

  2. If my deduction of the problem is wrong, what is the correct reason behind this issue?如果我对问题的推断是错误的,那么这个问题背后的正确原因是什么?

1+5 is an int so there is no problem using it to initialize a vector<int> entry. 1+5是一个int ,因此使用它来初始化vector<int>条目没有问题。

'r' + 's' is an int (236) which is out of range of char on your system. 'r' + 's'是一个int (236),它超出了系统上的char范围。 So there is a problem trying to use it to initialize a vector<char> entry.因此,尝试使用它来初始化vector<char>条目时出现问题。 This is exactly the sort of case that the rule about list initialization disallowing narrowing conversions was designed for.这正是关于列表初始化不允许缩小转换的规则所设计的那种情况。

You would get the same error for vector<char> x = { 'a', 'b', 123456 };对于vector<char> x = { 'a', 'b', 123456 };你会得到同样的错误。

Standalone char either has the same properties as signed char or unsigned char , which one it is is implementation-defined and some compilers have a switch to choose (eg -funsigned-char on GCC).独立char具有与signed charunsigned char相同的属性,它是实现定义的,并且一些编译器有一个开关可供选择(例如,GCC 上-funsigned-char )。 To be clear, it is still a distinct type in either case.需要明确的是,无论哪种情况,它仍然是一种独特的类型。


In your words, char was indeed signed in both the cases as Nathan Oliver explained in the comments.用你的话来说,正如 Nathan Oliver 在评论中解释的那样, char确实在这两种情况下都有签名。 The problem is that you have a wrong notion that the standalone char was unsigned in your case.问题是您有一个错误的概念,即在您的情况下独立char是未签名的。 Just because char ch = 'r' + 'z';只是因为char ch = 'r' + 'z'; compiled doesn't show that it is unsigned.编译并没有显示它是无符号的。 You probably thought that it was unsigned because 'r' + 'z' == 236 which doesn't fit into a signed char .您可能认为它是无符号的,因为'r' + 'z' == 236不适合带signed char No, it does fit into a signed char for the following reason:不,它确实适合signed char ,原因如下:

char ch = 'r' + 'z'; is an out-of-range conversion .超出范围的转换 Since C++20 the result will be -20 (assuming plain char is 8-bit signed as indicated by your earlier error message, and the system uses ASCII encoding), prior to that the result was implementation-defined.由于 C++20,结果将是-20 (假设普通字符是 8 位签名的,如您之前的错误消息所示,并且系统使用 ASCII 编码),在此之前结果是实现定义的。


So, don't assume things.所以,不要假设事情。 If you are confused whether char is signed or unsigned on your system, simply check CHAR_MIN .如果您对系统上的 char 是有符号还是无符号感到困惑,只需检查CHAR_MIN

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM