3

Given:

typedef struct { char val[SOME_FIXED_SIZE]; } AString;
typedef struct { unsigned char val[SOME_FIXED_SIZE]; } BString;

I want to add ostream operator << available for AString and BString.

std::ostream & operator<<(std::ostream &out, const AString &str)
{ 
   out.write(str.val, SOME_FIXED_SIZE);
   return out;
}

If I do the same for BString, the compiler complains about invalid conversion from 'const unsigned char*' to 'const char*'. The ostream.write does not have const unsigned char* as argument.

It seems << itself accepts the const unsigned char, so I try something like this

std::ostream & operator<<(std::ostream &out, const BString &str)
{ 
    for (int i=0; i<SOME_FIXED_SIZE; i++)
    {
        out<<str.val[i];
    }
    return out;
}

Can someone tell me if this is right/good practice or there are some better ways? welcome any comments!

Balanivash
  • 6,709
  • 9
  • 32
  • 48
pepero
  • 7,095
  • 7
  • 41
  • 72
  • I thought chars are by default unsigned. – balki Jul 06 '11 at 10:00
  • @balki That very much depends on your compiler settings; but in general, no. – Konrad Rudolph Jul 06 '11 at 10:05
  • The question is, what do you use `BString` for? If you really mean a textual string, then use the `char` version and all is well. If you have arbitrary binary data, then just printing to the output might not show anything meaningful or break your terminal. So why bother with two string classes? – Kerrek SB Jul 06 '11 at 10:11
  • two string classes are from legacy code. Honestly, I do not know why. I will figure it out and come back for this point. – pepero Jul 06 '11 at 10:15
  • @balki: The standard does not describe the signedness of `char`. In fact, `unsigned char`, `signed char` and `char` are three distinct datatypes, which you should keep in mind especially when overloading things and writing templates. – Sebastian Mach Jul 06 '11 at 10:21
  • 1
    @balki: Even if, on your platform, `char` is an unsigned type, it's still distinct from `unsigned char`. – Lightness Races in Orbit Jul 06 '11 at 10:23

2 Answers2

2

The simplest and cleanest solution is to create an std::string, e.g.:

out << std::string(str.val, str.val + sizeof(str.val));

However, the question is: do you want formatted or unformatted output? For unformatted output, as ugly as it is, I'd just use a reinterpret_cast.

James Kanze
  • 150,581
  • 18
  • 184
  • 329
0

Have you thought about casting it to char*:

std::ostream & operator<<(std::ostream &out, const BString &str)
{ 
   out.write(reinterpret_cast<char*>(str.val), sizeof(str.val));
   return out;
}
iammilind
  • 68,093
  • 33
  • 169
  • 336