You are not logged in.

#1 2016-11-19 16:19:32

mis
Member
Registered: 2016-03-16
Posts: 234

Proper fix for narrowing conversion error

Hi, compiling an old programm with gcc6 fails with some -Wnarrowing errors. Using -std=gnu++98 (edit: or -Wno-narrowing) solve the problem but now I'm wondering how to fix the sources properly.

Here is a small example (narrow.cpp)

#include <iostream>

int main(void)
{
    unsigned int a[3] = {1 ,2 ,-1};

    std::cout << a[2] << std::endl;
    return 0;
}

compiling with gcc6 defauld standard fails

g++ -o narrow narrow.cpp 
narrow.cpp: In function 'int main()':
narrow.cpp:5:32: error: narrowing conversion of '-1' from 'int' to 'unsigned int' inside { } [-Wnarrowing]
   unsigned int a[3] = {1 ,2 ,-1};
                                ^

The Porting to gcc-6 guide says: Narrowing conversions can be avoided by using an explicit cast

So I tried this (narrow-cast.cpp)

#include <iostream>                                                                                                                                                                          
                                                                                                                                                                                             
int main(void)                                                                                                                                                                               
{                                                                                                                                                                                            
  unsigned int a[3] = {1 ,2 ,(unsigned int)-1};                                                                                                                                              
                                                                                                                                                                                             
  std::cout << a[2] << std::endl;                                                                                                                                                            
  return 0;                                                                                                                                                                                  
}

Results:

g++ -std=gnu++98 -o narrow narrow.cpp 
g++ -o narrow-cast narrow-cast.cpp 

./narrow
4294967295

./narrow-cast 
4294967295

Looks good, but  I'm not sure if the cast is a proper fix or if there are any possible pitfalls?

Last edited by mis (2016-11-19 16:28:44)

Offline

#2 2016-11-19 16:45:48

ewaller
Administrator
From: Pasadena, CA
Registered: 2009-07-13
Posts: 19,774

Re: Proper fix for narrowing conversion error

In my mind, casting a signed value to an unsigned variable is an error.  Regardless, the conversion is to take the absolute value of the signed value, compliment each bit, and add one.  The resultant value, of course, is dependent on the size of int on the system.  A value of -1 therefore becomes 0b11111..1111.  IOW, the largest unsigned value that can be expresses as an unsigned int.

You will need to audit the code to determine where a[] is used, and determine what is the acceptable domain.  Is the domain all unsigned ints? or is it limited to the domain of a[] over the range 0..2?


Nothing is too wonderful to be true, if it be consistent with the laws of nature -- Michael Faraday
Sometimes it is the people no one can imagine anything of who do the things no one can imagine. -- Alan Turing
---
How to Ask Questions the Smart Way

Offline

#3 2016-11-19 17:23:18

mis
Member
Registered: 2016-03-16
Posts: 234

Re: Proper fix for narrowing conversion error

ewaller wrote:

In my mind, casting a signed value to an unsigned variable is an error.

Hm, that was my thought also.

ewaller wrote:

You will need to audit the code to determine where a[] is used, and determine what is the acceptable domain.  Is the domain all unsigned ints? or is it limited to the domain of a[] over the range 0..2?

It's a mp3 player siftware and the code in question is a huffman table.

typedef struct
{
  int tablename;
  unsigned int xlen,ylen;
  unsigned int linbits;
  unsigned int treelen;
  const unsigned int (*val)[2];
}HUFFMANCODETABLE;

The narrowing coversion is where such a struct is declared and initialized. Some values are -1

But ok, to determine if the cast wouldn't break anything is above my skills and seems too much work.

I'll stick with -std=gnu++98 for the moment...

edit:
Hm.. but then comes the question to mind how it's handled by the gnu++98 standard?

Last edited by mis (2016-11-19 17:25:56)

Offline

#4 2016-12-13 04:29:54

dimich
Member
From: Kharkiv, Ukraine
Registered: 2009-11-03
Posts: 240

Re: Proper fix for narrowing conversion error

I guess most correct way is to use std::numeric_limits<unsigned int>::max() value instead of -1.

Offline

Board footer

Powered by FluxBB