• Advertisement
Sign in to follow this  

byte,char exactly 8 bits?

This topic is 4339 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

How can I make sure the variable i use for a byte is exactly 8 bits atm I am using a char but i get this warning warning C4309: 'default argument' : truncation of constant value at char aa = 254

Share this post


Link to post
Share on other sites
Advertisement
unsigned char should be 8 bits on most, but not all systems.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
the char is signed .. make it unsigned

Share this post


Link to post
Share on other sites
The trouble here is that aa is a char, but 254 is an int, so the compiler is warning that the int is being truncated to a char. Since 254 is small enough, there won't be any real problem, but the warnings are annoying. You can just cast the 254 to a char to get rid of the warning:

char aa = (char)254;

To be safe when going back and forth between chars and ints, you should use unsigned types to prevent sign extension.

Share this post


Link to post
Share on other sites
Just to re-iterate, the real problem with your code is as the Anonymous Poster said - a char will only hold values from -128 to +127, while an unsigned char will hold values from 0-255. Thus, in this instance, you should be using an unsigned char.

You should also explicitly type-cast as Date Hunt suggested.

Share this post


Link to post
Share on other sites
I think the 'truncation' in the warning means: cannot store the value because it's too big. That would say that the compiler thinks the value is of type int, so I say that Dave is right.

And I read somewhere that most compilers have 'unsigned' on chars by default.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
typedef char byte;

Fixed a typo.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Sorry, that should be

typedef unsigned char byte;

ofcourse...

Share this post


Link to post
Share on other sites
Quote:
Original post by Pipo DeClown
And I read somewhere that most compilers have 'unsigned' on chars by default.


I wouldn't count on it though [wink]

And yeah, use a typedef - they were made for this kind of thing.

Share this post


Link to post
Share on other sites
Bah, more type safety is often a good thing:

struct byte {
typedef unsigned char value_type;
value_type v;
byte(const byte&b):v(b.v){};
explicit byte(const unsigned char v_):v(v_){};
void swap(byte&b) {std::swap(v, b.v);};
value_type value() {return v;}
bool iszero() {return !v;}
byte& operator=(const byte&b) {byte tmp = b; swap(tmp); return *this;}
bool operator==(const byte&b) const {return v==b.v;};
bool operator!=(const byte&b) const {return v!=b.v;};
bool operator<=(const byte&b) const {return v<=b.v;};
bool operator>=(const byte&b) const {return v>=b.v;};
bool operator< (const byte&b) const {return v< b.v;};
bool operator> (const byte&b) const {return v> b.v;};
byte operator| (const byte&b) const {return byte(v|b.v);};
byte operator& (const byte&b) const {return byte(v&b.v);};
byte operator^ (const byte&b) const {return byte(v^b.v);};
byte&operator|=(const byte&b) {return *this=(*this|b);}
byte&operator&=(const byte&b) {return *this=(*this&b);}
byte&operator^=(const byte&b) {return *this=(*this^b);}
byte operator~ () const {return byte(~v);};
byte operator<<(int a) const {return byte(v<<a);};
byte operator>>(int a) const {return byte(v>>a);};
};


A byte class that takes the same storage as an unsigned char that should be reduced by any decent optimizer to being just an unsigned char -- but is type incompatable with unsigned chars.

Share this post


Link to post
Share on other sites
Quote:
Original post by extralongpants
Just to re-iterate, the real problem with your code is as the Anonymous Poster said - a char will only hold values from -128 to +127, while an unsigned char will hold values from 0-255. Thus, in this instance, you should be using an unsigned char.

You should also explicitly type-cast as Date Hunt suggested.


Whether a char is signed or unsigned is implementation defined. If you are using a char for numerical (as opposed to character) data then you should specify signed char or unsigned char. Note also that char is a distinct type and is neither a signed char nor an unsigned char, although its representation will be identical to one of them.

Σnigma

[Edited by - Enigma on April 5, 2006 10:09:57 AM]

Share this post


Link to post
Share on other sites
Quote:
Original post by Enigma
Quote:
Original post by extralongpants
Just to re-iterate, the real problem with your code is as the Anonymous Poster said - a char will only hold values from -128 to +127, while an unsigned char will hold values from 0-255. Thus, in this instance, you should be using an unsigned char.

You should also explicitly type-cast as Date Hunt suggested.


Whether a char is signed or unsigned is implementation defined. If you are using a char for numerical (as opposed to character) data then you should specify signed char or unsigned char. Note also that char is a distict type and is neither a signed char nor an unsigned char, although its representation will be identical to one of them.

Σnigma


Thanks for the clarification. I wasn't actually aware that a char was not inherently signed or unsigned. It makes sense though.

Share this post


Link to post
Share on other sites
Quote:
Original post by NotAYakk
Bah, more type safety is often a good thing:

struct byte {
typedef unsigned char value_type;
value_type v;
byte(const byte&b):v(b.v){};
explicit byte(const unsigned char v_):v(v_){};
void swap(byte&b) {std::swap(v, b.v);};
value_type value() {return v;}
bool iszero() {return !v;}
byte& operator=(const byte&b) {byte tmp = b; swap(tmp); return *this;}
bool operator==(const byte&b) const {return v==b.v;};
bool operator!=(const byte&b) const {return v!=b.v;};
bool operator<=(const byte&b) const {return v<=b.v;};
bool operator>=(const byte&b) const {return v>=b.v;};
bool operator< (const byte&b) const {return v< b.v;};
bool operator> (const byte&b) const {return v> b.v;};
byte operator| (const byte&b) const {return byte(v|b.v);};
byte operator& (const byte&b) const {return byte(v&b.v);};
byte operator^ (const byte&b) const {return byte(v^b.v);};
byte&operator|=(const byte&b) {return *this=(*this|b);}
byte&operator&=(const byte&b) {return *this=(*this&b);}
byte&operator^=(const byte&b) {return *this=(*this^b);}
byte operator~ () const {return byte(~v);};
byte operator<<(int a) const {return byte(v<<a);};
byte operator>>(int a) const {return byte(v>>a);};
};


A byte class that takes the same storage as an unsigned char that should be reduced by any decent optimizer to being just an unsigned char -- but is type incompatable with unsigned chars.


Where is the subtraction,addition,multiplication,and division overloads?

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
The standard specifies that char objects must always be at _least_ 8 bits long, though they can always be more.

Share this post


Link to post
Share on other sites
Quote:
Original post by Kambiz
You can use "__int8" or "unsigned __int8".
MSDN Link.


Which, unfortunately (or fortunately), only works on Microsoft's compilers.

Share this post


Link to post
Share on other sites
Quote:
Original post by dawidjoubert
Quote:
Original post by NotAYakk
Bah, more type safety is often a good thing:

struct byte {
typedef unsigned char value_type;
value_type v;
byte(const byte&b):v(b.v){};
explicit byte(const unsigned char v_):v(v_){};
void swap(byte&b) {std::swap(v, b.v);};
value_type value() {return v;}
bool iszero() {return !v;}
byte& operator=(const byte&b) {byte tmp = b; swap(tmp); return *this;}
bool operator==(const byte&b) const {return v==b.v;};
bool operator!=(const byte&b) const {return v!=b.v;};
bool operator<=(const byte&b) const {return v<=b.v;};
bool operator>=(const byte&b) const {return v>=b.v;};
bool operator< (const byte&b) const {return v< b.v;};
bool operator> (const byte&b) const {return v> b.v;};
byte operator| (const byte&b) const {return byte(v|b.v);};
byte operator& (const byte&b) const {return byte(v&b.v);};
byte operator^ (const byte&b) const {return byte(v^b.v);};
byte&operator|=(const byte&b) {return *this=(*this|b);}
byte&operator&=(const byte&b) {return *this=(*this&b);}
byte&operator^=(const byte&b) {return *this=(*this^b);}
byte operator~ () const {return byte(~v);};
byte operator<<(int a) const {return byte(v<<a);};
byte operator>>(int a) const {return byte(v>>a);};
};


A byte class that takes the same storage as an unsigned char that should be reduced by any decent optimizer to being just an unsigned char -- but is type incompatable with unsigned chars.


Where is the subtraction,addition,multiplication,and division overloads?


And >>=, <<=, and - (negate, not subract) ?

Share this post


Link to post
Share on other sites
Quote:
Original post by smart_idiot
Quote:
Original post by dawidjoubert

Where is the subtraction,addition,multiplication,and division overloads?


And >>=, <<=, and - (negate, not subract) ?


I forgot >>= and <<=. Ooops. =) Serves me right for doing whole-cloth coding in a forum.

I would assume that byte as a type are raw binary data (not 8 bit integers), so I would actually be against having +,-,/,*.

But if you just want a strong_typedef, implement:
template<typename data, typename tag_type>
struct strong_typedef { /* boilerplate code here */ };

struct byte_tag;
typedef strong_typedef<unsigned char, byte_tag*> byte;


strong_typedef would act like the above byte class (no implicit casts).

The tag_type would be unused anywhere in the implementation -- it's purpose is to make the typedef strong.

You'd also want to implement raw() non-member methods (that just call value()).

Random:
why doesn't C++ have an
operator===
;)

PS: I also forgot the trivial constructor. =)

Share this post


Link to post
Share on other sites
char is defaulting to signed, meaning it is between -128 and +127.
So yes 254 is overflowing that.

Share this post


Link to post
Share on other sites
Quote:
Original post by iMalc
char is defaulting to signed, meaning it is between -128 and +127.
So yes 254 is overflowing that.


No it's not. char, signed char and unsigned char are all different types. char can act as an unsigned char or signed char, it depends on the compiler.

EDIT:

From the standard (3.9.1)
Quote:
Objects declared as characters (char) shall be large enough to store any member of the implementation’s basic character set. If a character from this set is stored in a character object, the integral value of that character object is equal to the value of the single character literal form of that character. It is implementation defined whether a char object can hold negative values. Characters can be explicitly declared unsigned or signed. Plain char, signed char, and unsigned char are three distinct types. A char, a signed char, and an unsigned char occupy the same amount of storage and have the same alignment requirements (3.9); that is, they have the same object representation. For character types, all bits of the object representation participate in the value representation. For unsigned character types, all possible bit patterns of the value representation represent numbers. These requirements do not hold for other types. In any particular implementation, a plain char object can take on either the same values as a signed char or an unsigned char; which one is implementation-defined.

Share this post


Link to post
Share on other sites
Quote:
Original post by CTar
Quote:
Original post by iMalc
char is defaulting to signed, meaning it is between -128 and +127.
So yes 254 is overflowing that.


No it's not. char, signed char and unsigned char are all different types. char can act as an unsigned char or signed char, it depends on the compiler.

"char is defaulting" not "char defaults." As your quote indicates, whether it defaults to being a signed or unsigned type is implementation defined. In this case, the implementation is clearly defaulting to a signed type. His post was still pointless given the discussion that already took place, but it was hardly wrong.

NotAYakk: I'm not entirely sure why you added an assignment operator, but I am certain you chose a rather silly way to implement it.

CM

Share this post


Link to post
Share on other sites
Quote:
Original post by dawidjoubert
How can I make sure the variable i use for a byte is exactly 8 bits


check the value of std::numeric_limits<char>::digits (in <limits>).

If you definitely want an 8-bit type, check out <stdint.h> if you have a C99 compiler, and use the int8_t type it defines. If you don't have a C99 compiler, you can use the equivalent facilities provided by the Boost C++ libraries.

Quote:
atm I am using a char but i get this warning
warning C4309: 'default argument' : truncation of constant value
at
char aa = 254


Unlike the other types, char may be signed or unsigned. If you explicitely want one or the other, use signed char or unsigned char

Share this post


Link to post
Share on other sites
The C standard actually defines a way of doing variables with guaranteed sizes. The includes stdint.h and inttypes.h (can't remember exactly which one you'll need) provides types like uint8_t. It's best to use types like these, being explicit rather than saying "this char is really an 8-bit value".

Of course, this whole point is moot. In typical Microsoft style, they chose to ignore this part of the standard. Even though implementing this part of the standard would mean only writing a few very small header files, it just never got done. Instead, they have their own non-standard types for variables of specified size, but I can't remember their names. Look it up in MSDN, be as explicit as possible about your data types. If it's intended to hold a character, use a char. If it's intended to hold 1 byte of data, use something like uint8_t.

Share this post


Link to post
Share on other sites
Quote:
Original post by NotAYakk
Bah, more type safety is often a good thing:


Yes, but I somehow don't think you really need to implement a copy constructor and assignment operator - especially not with copy-and-swap idiom - for a POD type :)

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement