简体   繁体   中英

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

I have this line in my code:

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

The it is an iterator which points to one of these:

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

All the fields are unsigned. When compiling I get the following error:

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]

This concerns the it->gc / 5 argument being passed to Locus . The corresponding field in Locus is also a uint16_t .

I'm confused as to why the compiler is doing all these implicit casts here. If I change the expression to it->gc / uint16_t(5) I still get the same error which raises the question of why the compiler is casting things to integer when they are the same type.

Does the division operator automatically cast arguments to int?

Does the division operator automatically cast arguments to int?

Promote, not cast, but yes. See Implicit conversions: Integral promotion on cppreference.com:

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.

You are trying to assign the result of it->gc / 5 to a uint16_t field, which normally isn't a problem during an assignment, eg:

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

However, such a narrowing conversion from a larger integer to a smaller integer is not allowed inside of a brace initializer:

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 can't represent all of the values of an int , hence the error.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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