【问题标题】:Declaring a variable with two types: "int char"声明具有两种类型的变量:“int char”
【发布时间】:2018-12-16 18:56:58
【问题描述】:

我是 C++ 初学者,我正在阅读 Bjarne Stroustrup 的《编程:使用 C++ 的原则和实践》

3.9.2 不安全的转换部分,作者提到了

当初始值设定项是整数文字时,编译器可以检查实际值并接受不意味着缩小的值:

int char b1 {1000};     // error: narrowing (assuming 8-bit chars)

我对这个声明感到困惑。它使用两种类型(intchar)。我以前从未在 Java 和 Swift 中看到过这样的声明(我比较熟悉的两种语言)。这是拼写错误还是有效的 C++ 语法?

【问题讨论】:

  • 你有这本书的哪个版本和印刷版?您是否查找过本书的勘误表?
  • 那你读的是什么版本?我确定 Bjarne 想知道这个错误。
  • 3.9.2 不安全转换 不安全转换是指一个值可以隐式转换为不等于原始值的另一种类型的值。例如:int i = 20000;字符 c = i;这种转换称为“缩小”转换。 double to int, char or bool int to char or bool char to bool
  • float char 是另一种有用的类型,尤其是在游泳池中。有些配有啤酒架。
  • 这是拼写错误还是有效的 C++ 语法? Try it(好的,好的,不,它无效)。

标签: c++ type-conversion initialization uniform-initialization narrowing


【解决方案1】:

这在 C/C++ 语法中是错误的。除了unions(请参阅@Alex 答案)之外,还有一种 C++ 方法可以只存储一种称为std::variant(类型安全联合)的可用类型:

#include <variant>
#include <string>

int main()
{
    std::variant<int, float> v, w;
    v = 12; // v contains int
    int i = std::get<int>(v);
    w = std::get<int>(v);
    w = std::get<0>(v); // same effect as the previous line
    w = v; // same effect as the previous line

//  std::get<double>(v); // error: no double in [int, float]
//  std::get<3>(v);      // error: valid index values are 0 and 1

    try {
      std::get<float>(w); // w contains int, not float: will throw
    }
    catch (std::bad_variant_access&) {}

    std::variant<std::string> v("abc"); // converting constructors work when unambiguous
    v = "def"; // converting assignment also works when unambiguous
}

【讨论】:

    【解决方案2】:

    这是错误的。 在 C/C++ 中,多类型声明可以通过使用联合来实现。例如:

    union {
        int i;
        char c;
    } var;
    
    var.i = 42;
    /* OR */
    var.c = ‘c’;
    

    存储是相同的,因此 .c 和 .i 只是针对相同值的每个类型的句柄。

    【讨论】:

      【解决方案3】:

      这是书中的一个错误。这不是一个有效的 C++ 声明,即使没有所谓的缩小转换。

      不过,Bjarne Stroustrup's page(第 4 版及更早版本)的任何勘误表中都没有提到它,这很奇怪。这是一个足够明显的错误。我想,因为它是用//error 评论的,所以很少有人注意到声明本身的错误。

      【讨论】:

      • 书中预期的代码示例可能是什么?
      • @Hamsterrific char b1 {1000}; (因为这会引发评论中提到的错误)。我猜 Bjarne 那天打字的手指很累。
      • @PaulSanders 累了吗?他在那里输入了一个额外的int! :-)
      • @LeoHeinsaar 哈哈。好吧,咖啡太多了 :) 或者他有口吃 :)
      • 是的:手指累了。它看起来像是前面示例中的剪切粘贴错误。在前面的例子中,他给出了两行:int a {1000}; // OK [\n] char b {a} // 错误:int -> char 可能会缩小 [\n] 并且他似乎已经将该示例剪切并粘贴到下一个示例中并且错过了删除“int”部分: int char b1 {1000}; // 错误:缩小(假设 8 位字符)[\n] char b2 {48}; // 确定 [\n]
      【解决方案4】:

      书错了。

      标记序列int char b1{1000}; 在语义上不是有效的 C++。

      你试图用一种以上的类型声明b1,这是没有意义的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-06-26
        • 2020-07-13
        • 2020-10-13
        • 2015-05-13
        • 2018-04-22
        • 2019-07-20
        相关资源
        最近更新 更多