C++ 为什么 uint16_t 在这里隐式转换为 int?

C++ Why is the uint16_t being implicitly cast to int here?

我的代码中有这一行:

Locus locus({track.chrom, track.begin, LOCUS_TYPE_INNER, it->left, it->right, it->gc / 5, true}) ;

it 是一个指向其中之一的迭代器:

struct SimpleKmer {
    uint64_t kmer ;
    uint64_t left ;
    uint64_t right ;
    uint16_t gc ;
};

所有字段均未签名。编译时出现以下错误:

warning: narrowing conversion of ‘(int)(((short unsigned int)((int)it.KmerIterator::operator->()->SimpleKmer::gc)) / 5)’ from ‘int’ to ‘uint16_t’ {aka ‘short unsigned int’} inside { } [-Wnarrowing]

这涉及传递给 Locusit->gc / 5 参数。 Locus中对应的字段也是uint16_t.

我很困惑编译器为什么要在这里进行所有这些隐式转换。如果我将表达式更改为 it->gc / uint16_t(5),我仍然会遇到相同的错误,这引发了一个问题,即当它们是相同类型时,为什么编译器将它们转换为整数。

除法运算符是否自动将参数转换为 int?

Does the division operator automatically cast arguments to int?

宣传,不是演员,但是。请参阅 cppreference.com 上的 Implicit conversions: Integral promotion

In particular, arithmetic operators do not accept types smaller than int as arguments, and integral promotions are automatically applied after lvalue-to-rvalue conversion, if applicable. This conversion always preserves the value.

您正在尝试将 it->gc / 5 的结果分配给 uint16_t 字段,这在分配过程中通常不是问题,例如:

uint16_t field;
field = it->gc / 5; // OK

但是,在大括号初始值设定项中不允许进行这种从较大整数到较小整数的缩小转换:

List Initialization

Narrowing conversions

list-initialization limits the allowed implicit conversions by prohibiting the following:

  • ...

  • 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

  • ...

A uint16_t 不能表示 int 的所有值,因此出现错误。