Narrowing conversion of

What does this mean ?

1
2
3
     ^
/home/cmisip/NetBeansProjects/ZoneMinder/src/zm_ffmpeg_camera.cpp:231:54: warning: narrowing conversion of ‘(((int)mv->AVMotionVector::dst_x) & 255)’ from ‘int’ to ‘uint8_t {aka unsigned char}’ inside { } is ill-formed in C++11 [-Wnarrowing]
                         uint8_t x8bit[2]={ mv->dst_x & 0xff, mv->dst_x >> 8 };


mv->dst_x and mv_dst_y are non negative int16_t. I am splitting it into two uint8_t. Is it because the compiler doesn't know that I have a separate operation for the other half of the int_16t?

Thanks,
Chris
Last edited on
my mind reading cat says «miau».
it looks like you took an int, which is probably 32 or 64 bits long, and stuffed it into an 8 bit type. that works, but if the value is greater than 255 it may not work as expected. This is just a warning, if you know you are doing the right thing you can make the warning go away by explicitly casting the operation. Or you can just ignore it, but that is not good style.
Sorry, the code in question is just one line

 
uint8_t x8bit[2]={ mv->dst_x & 0xff, mv->dst_x >> 8 };


I'm splitting a positive 16bit int into 2 8bit ints. I wasn't sure if it was something I needed to worry about. It sounds like I shouldn't. I just noted that the IDE was highlighting it subtly in yellow. I am trying to find out the reason for a spike in value after reassembling the 8 bit ints into 16 bit. Sounds like I have to look elsewhere.

Thanks,
Chris
Since C++11, {} initialization doesn't allow narrowing conversions.

In your code you are relying on implicit conversion from int to uint8_t which is considered a narrowing conversion because not all values of int can be stored in a uint8_t.

If you are sure you want to make this conversion you should use explicit casting.

1
2
3
4
5
uint8_t x8bit[2] = 
{
	static_cast<uint8_t>(mv->dst_x & 0xff), 
	static_cast<uint8_t>(mv->dst_x >> 8)
};


Some compilers still allow narrowing conversions and only show a warning but it's actually an error according to the C++ standard.

http://www.stroustrup.com/C++11FAQ.html#narrowing
I have a personal preference to avoid cryptic bitwise stuff and generally use a union.
with some better names and namespaces wrapped around this for clean code, but the general concept:

enum
{
high,low,emax
};
union u
{
uint16_t u16;
uint8_t highlow[emax];
};

...
u x;
x.u16 = 0x1234;
cout << x.highlow[high] <<" " << x.highlow[low] << endl;

//note that high and low are subject to endian issues and may need to be inverted in the enum to get the expected values.

Its not any better, its just another way to do it. Its extra helpful when dealing with 64 bit ints and 8 individual bytes therein.
Last edited on
iirc, that's incorrect.
if you write into a field you can't read another one (undefined behaviour)

http://en.cppreference.com/w/cpp/language/union
it's undefined behavior to read from the member of the union that wasn't most recently written
Last edited on
Interesting. Its worked for decades, documentation aside, but that is a weird, unnecessary restriction. Makes unions about worthless -- their biggest value to me has been for serialization.

Ah, and then they say:

Many compilers implement, as a non-standard language extension, the ability to read inactive members of a union.

Sigh. Good catch!
Last edited on
Thanks guys,
I just realized that it was possible to memcpy a 2byte variable into a malloc'd pointer and read that 2 bytes from that pointer address into a 2byte variable.

I initially assumed that a malloc derived pointer address must only have single bytes written into it. Therefore, to write a multi byte variable, I need to decompose into single byte values.

I will post another question regarding possiblity of alignment errors with this technique in another thread.

Chris

That is woefully inefficient. It does not really matter, once, but if you are doing a large number of copies this way in a loop or something, it could be slower than necessary. You can directly copy with memcpy.

Are you saying you are doing the second thing here to accomplish the first?
short s;
...
short s2 = s;

compared to
short s;
something * p;
memcpy(p,s,2);
short s2 = (short*)p[0];


I am doing a large number of copies in a loop but it was necessary to move data from one process space to another. I put the code and the question in this thread.

http://www.cplusplus.com/forum/general/219108/

Thanks,
Chris
Topic archived. No new replies allowed.