0

I have inherited some C++ code that sets up a serial com port in Windows. The code contains the following declaration and method, which I have simplified for the purposes of this question.

std::queue<std::string> m_queue;

SendMsg( const char* dataBuff, unsigned int dataBuffSz )
{
       // Insert into the end of the queue to send
        m_queue.emplace( dataBuff, dataBuffSz );
        
}

If I create a suitable object to invoke SendMsg then the following is valid and is successfully transmitted across the serial link

mySerialLinkObject->SendMsg( "Hello", 5 );

// or alternatively
char hexBytes[4] = { 0x01, 0x02, 0x0F, 0x7F };
mySerialLinkObject->SendMsg( hexBytes, 4 );

My specific requirements for this link are for it to be able to send hex bytes in the range 0x00 to 0xFF however if I declare

char hexBytes[2] = { 0x80, 0xFF };

In Visual Studio 2015 I get the following build output from the declaration of hexBytes line above

error C2220: warning treated as error - no 'object' file generated warning C4838: conversion from 'int' to 'char' requires a narrowing conversion note: to simplify migration, consider the temporary use of /Wv:18 flag with the version of the compiler with which you used to build without warnings warning C4309: 'initializing': truncation of constant value

If I change my hexBytes definition as follows

uint8_t hexBytes[2] = { 0x80, 0xFF }; //unsigned char fixed width

This fixes the initial compiler error and if I then overload the SendMsg method to

SendMsg( const uint8_t* dataBuff, unsigned int dataBuffSz )
{
       // Insert into the end of the queue to send
        m_queue.emplace( dataBuff, dataBuffSz );
         
}

Then I get a whole load of std::queue related compiler errors

xmemory0(737): error C2664: 'std::basic_string<char,std::char_traits,std::allocator>::basic_string(std::initializer_list<_Elem>,const std::allocator &)': cannot convert argument 1 from 'const uint8_t *' to 'const std::basic_string<char,std::char_traits,std::allocator> &' 1> with 1> [

Its not my code so I don't really understand what it did initially when it placed the char* parameter in to a queue of std::string and why I am not allowed by the compiler to place "unsigned char*" in to the std::string queue.

Im not sure what the best way to fix this.

Do I fix the initial C4838 error when declaring hexBytes by doing some form of conversion, In which case I am not sure how?

Or do I somehow try to fix the std::queue errors I am getting. Again I'm not sure of the best way to achieve that

jt1995SCO
  • 1
  • 2

1 Answers1

1

According to the ISO C++ standard, it is implementation defined whether a char has the same representation as an signed char or an unsigned char.

On Microsoft Visual Studio, with default settings, a char has the same representation as a signed char, which is able to represent numbers in the range of -128 to 127.

Therefore, it is not possible to put numbers in the range 0x80 (decimal 128) to 0xFF (decimal 255) into a char array. However, you can put it into a char array in such a way that it would have the same memory representation as if the array were of type uint8_t, by writing

char hexBytes[2] = { (char)0x80, (char)0xFF };

instead of:

char hexBytes[2] = { 0x80, 0xFF };

On the other hand, it would be very cumbersome to perform a cast for every value. Therefore, it would probably be easier to define the array as a string literal

char hexBytes[] = "\x80\xFF";

which would waste one byte for the terminating null character.

Or you could define the array as type uint8_t and cast the decayed pointer to char*, like this:

uint8_t hexBytes[2] = { 0x80, 0xFF };
mySerialLinkObject->SendMsg( reinterpret_cast<char*>(hexBytes), 2 );

That way, it is not necessary to overload the function SendMsg and you won't have any std::queue or std::basic_string related compiler errors.

Andreas Wenzel
  • 22,760
  • 4
  • 24
  • 39