why unsigned char not work

M

Mug

hello
there i have a curious problem on fstream things,i tryed to read the
file with the unsigned char buffer,but compilater generate some
errors.
here's my program:

#include<iostream>
#include<fstream>
#include<cstdio>
using namespace std;
int main(void)
{
unsigned char data_fetcher[2]; ;
/* if i declare char data_fetcher[2]; it will be ok but ...*/
char str[]="söfdsfsdfsd\n";
fstream data_file;
data_file.open("whatever",fstream::eek:ut|fstream::in|fstream::app);
data_file.write(str,5*sizeof(char));
data_file.seekg(0,ios::beg);
data_file.read(data_fetcher,2*sizeof(unsigned char));
printf("display : %d %d \n",data_fetcher[0],data_fetcher[1]);
/* but here the value of data_fetcher[1] will be negative, this is
what i tryed to avoid */
data_file.close();
return 0;
}

I really need to know why i can't use it,i used to do those thing with
C function "read",it works perfectly,
sometime i deal with char value superior then 127,so i need to use
unsigned char here,can somebody help?
thx
Mug
 
M

Michael Doubez

there i have a curious problem on fstream things,i tryed to read the
file with the unsigned char buffer,but compilater generate some
errors.

This has nothing to do with fstream. With unsigned, you have an error
because the compiler is kind enough to warn you about a mismatch with
types.
here's my program:

#include<iostream>
#include<fstream>
#include<cstdio>
using namespace std;
int main(void)
{
        unsigned char data_fetcher[2]; ;
/* if i declare char data_fetcher[2]; it will be ok but ...*/
        char str[]="söfdsfsdfsd\n";
        fstream data_file;
        data_file.open("whatever",fstream::eek:ut|fstream::in|fstream::app);
        data_file.write(str,5*sizeof(char));
        data_file.seekg(0,ios::beg);
        data_file.read(data_fetcher,2*sizeof(unsigned char));
        printf("display : %d %d \n",data_fetcher[0],data_fetcher[1]);
/* but here the value of data_fetcher[1] will be negative, this is
what i tryed to avoid */

On your system char must be signed and it is implicitely converted to
int when passed to printf() so it becomes negative.
        data_file.close();
        return 0;

}

I really need to know why i can't use it,i used to do those thing with
C function "read",it works perfectly,

Does it still work in this code if you use C read() function ?
sometime i deal with char value superior then 127,so i need to use
unsigned char here,can somebody help?

If your char is signed, 127 is the maximum value.

For your problem, print in unsigned format:
printf("display : %u %u \n",
data_fetcher[0],
data_fetcher[1]
);
 
M

Mug

there i have a curious problem on fstream things,i tryed to read the
file with the unsigned char buffer,but compilater generate some
errors.

This has nothing to do with fstream. With unsigned, you have an error
because the compiler is kind enough to warn you about a mismatch with
types.


here's my program:
#include<iostream>
#include<fstream>
#include<cstdio>
using namespace std;
int main(void)
{
        unsigned char data_fetcher[2]; ;
/* if i declare char data_fetcher[2]; it will be ok but ...*/
        char str[]="söfdsfsdfsd\n";
        fstream data_file;
        data_file.open("whatever",fstream::eek:ut|fstream::in|fstream::app);
        data_file.write(str,5*sizeof(char));
        data_file.seekg(0,ios::beg);
        data_file.read(data_fetcher,2*sizeof(unsigned char));
        printf("display : %d %d \n",data_fetcher[0],data_fetcher[1]);
/* but here the value of data_fetcher[1] will be negative, this is
what i tryed to avoid */

On your system char must be signed and it is implicitely converted to
int when passed to printf() so it becomes negative.
        data_file.close();
        return 0;

I really need to know why i can't use it,i used to do those thing with
C function "read",it works perfectly,

Does it still work in this code if you use C read() function ?
yes it work perfect with C function read
sometime i deal with char value superior then 127,so i need to use
unsigned char here,can somebody help?

If your char is signed, 127 is the maximum value.

For your problem, print in unsigned format:
 printf("display : %u %u \n",
    data_fetcher[0],
    data_fetcher[1]
    );
with %u it give me a very big integer:
ocean% ./a.out
display : 115 4294967235thanks you advices,i just found a solution,
i keep the unsigned char declaration,
but in function
data_file.read(data_fetcher,2*sizeof(unsigned char));
i do a cast on first argument:
data_file.read((char*)data_fetcher,2*sizeof(unsigned char));
then it works perferct,result:
ocean% ./a.out
display : 115 195

i just realized that the type control in C++ is much strict then in C
thx
Mug
 
J

James Kanze

there i have a curious problem on fstream things,i tryed to
read the file with the unsigned char buffer,but compilater
generate some errors.
here's my program:
#include<iostream>
#include<fstream>
#include<cstdio>
using namespace std;
int main(void)
{
unsigned char data_fetcher[2]; ;
/* if i declare char data_fetcher[2]; it will be ok but ...*/
char str[]="söfdsfsdfsd\n";
fstream data_file;
data_file.open("whatever",fstream::eek:ut|fstream::in|fstream::app);
data_file.write(str,5*sizeof(char));
data_file.seekg(0,ios::beg);
data_file.read(data_fetcher,2*sizeof(unsigned char));

The line above shouldn't compile. istream::read requires a
char*, not an unsigned char*. You need a reinterpret_cast to
make it compile.
printf("display : %d %d \n",data_fetcher[0],data_fetcher[1]);
/* but here the value of data_fetcher[1] will be negative, this is
what i tryed to avoid */

If data_fetcher really is unsigned char[], then any output of a
negative value here would indicate an error dans le compiler.
data_file.close();
return 0;
}
I really need to know why i can't use it,i used to do those
thing with C function "read",it works perfectly,

I suspect that you've miscopied something, somewhere. The only
difference between istream::read and fread is that fread takes a
void*, but istream::read a char*, so there is an implicit
conversion data_fetcher to the parameter type for fread, but not
for istream::read. (There is no C function read, only a Posix
one. Which also takes a void*.)
sometime i deal with char value superior then 127,so i need to
use unsigned char here,can somebody help?

The issue is trickier than you realize. At one point (a long
time ago, in C), I thought that I'd use unsigned char, rather
than char, for text, precisely to avoid "negative" encodings.
In practice, it doesn't work; char and char* are too implicated
in the system (library functions, string literals, etc.) to be
avoided. The only solution is to explicitly cast to unsigned
char when (and only when) you need to avoid the negative values.
 
J

James Kanze

This has nothing to do with fstream. With unsigned, you have
an error because the compiler is kind enough to warn you about
a mismatch with types.
here's my program:
#include<iostream>
#include<fstream>
#include<cstdio>
using namespace std;
int main(void)
{
unsigned char data_fetcher[2]; ;
/* if i declare char data_fetcher[2]; it will be ok but ...*/
char str[]="söfdsfsdfsd\n";
fstream data_file;
data_file.open("whatever",fstream::eek:ut|fstream::in|fstream::app);
data_file.write(str,5*sizeof(char));
data_file.seekg(0,ios::beg);
data_file.read(data_fetcher,2*sizeof(unsigned char));
printf("display : %d %d \n",data_fetcher[0],data_fetcher[1]);
/* but here the value of data_fetcher[1] will be negative, this is
what i tryed to avoid */
On your system char must be signed and it is implicitely
converted to int when passed to printf() so it becomes
negative.

Except that in the posted code, data_fetcher is unsigned char,
so cannot be converted to a negative value. (But he has
probably miscopied his code, since the "data_file.read" line
shouldn't compile if data_fetcher is unsigned char[].)
Does it still work in this code if you use C read() function ?

The name of the function, in C, is fread. And the difference is
that fread takes a void*, rather than a char*, so you can pass
it an unsigned char*. If what is being read is text, however,
putting it into an unsigned char[] is just an invitation for
later problems. What he really needs to do is cast the char to
unsigned char when (and only when) he is concerned with its
numeric value.
If your char is signed, 127 is the maximum value.
For your problem, print in unsigned format:
printf("display : %u %u \n",
data_fetcher[0],
data_fetcher[1]
);

If data_fetcher is char, and char is signed, that won't work
either, since the promotion to int will result in a negative
int, which, interpreted as an unsigned, will result in a very,
very big number. If data_fetcher is char, his line should read:

printf( "display: %d %d\n",
static_cast< unsigned char >( data_fetcher[ 0 ] ),
static_cast< unsigned char >( data_fetcher[ 1 ] ) ) ;

Pretty, it ain't, but it's about the only real solution, given
that the authors of the C standard allow char to be signed.
 
S

Stephen Horne

Except that in the posted code, data_fetcher is unsigned char,
so cannot be converted to a negative value. (But he has
probably miscopied his code, since the "data_file.read" line
shouldn't compile if data_fetcher is unsigned char[].)

I haven't checked, but I have a feeling that this compiles in VC++,
possibly depending on compiler options. The obvious option to try
would be treating 'char' as unsigned. I haven't read this thread
carefully enough to be sure this is relevant - just a thought.

Does the standard really require "char" to be treated as a separate
type from "unsigned char"? My impression was that the signedness of
"char" isn't specified, and that types that are spelled differently
but have the same representation etc may or may not be treated as
distinct for overloading etc. For example, on 32 bit platforms, "int"
and "long int" are IIRC sometimes distinct types for overloading and
sometimes not, depending on the compiler. I would expect the same to
apply to "char" and either "signed char" or "unsigned char".
 
A

Alf P. Steinbach

* Stephen Horne:
Does the standard really require "char" to be treated as a separate
type from "unsigned char"?
Yes.


My impression was that the signedness of
"char" isn't specified,
Yes.

and that types that are spelled differently
but have the same representation etc may or may not be treated as
distinct for overloading etc.
Nope.


For example, on 32 bit platforms, "int"
and "long int" are IIRC sometimes distinct types for overloading and
sometimes not, depending on the compiler.
Nope.


I would expect the same to
apply to "char" and either "signed char" or "unsigned char".

Nope.


Possibly you've got this incorrect impression from standard library types like
'size_t', which can be just 'typedef' synonyms for other types.


Cheers & hth.,

- Alf
 
J

Jerry Coffin

[ ... ]
Does the standard really require "char" to be treated as a separate
type from "unsigned char"? My impression was that the signedness of
"char" isn't specified, and that types that are spelled differently
but have the same representation etc may or may not be treated as
distinct for overloading etc.

§3.9.1/1:
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.

The "three distinct types" part means that they are always separate
for purposes like overloading.
For example, on 32 bit platforms, "int"
and "long int" are IIRC sometimes distinct types for overloading and
sometimes not, depending on the compiler. I would expect the same to
apply to "char" and either "signed char" or "unsigned char".

The rules are the same for char and int -- but the rule in both cases
is that each type is always separate and always supports overloading.
 
S

Stephen Horne


OK - that clears that one up. Thanks.
Possibly you've got this incorrect impression from standard library types like
'size_t', which can be just 'typedef' synonyms for other types.

No - I'm pretty sure there were real
is-this-a-distinct-type-or-an-alias issues prior to the C++98
standard, back in the days of Borland C++ 5, Visual C++ 5 etc.
Probably that was due to C++ compilers being built on top of C
compilers - since C didn't (still doesn't AFAIK) have overloading, and
given implicit conversions, the issue of whether e.g. "int" and "long
int" were different types was a bit of a non-issue for C. Probably
more of a compiler design decision than a language semantics issue -
until you start adding the C++ support, of course.

I just assumed that (like many things in C and C++) this would be left
unspecified in the standard, I guess. With decade-or-more old
misconceptions, it's hard to be sure where they came from. Why it
lasted so long is easier - I never questioned it.
 
J

James Kanze

Except that in the posted code, data_fetcher is unsigned
char, so cannot be converted to a negative value. (But he
has probably miscopied his code, since the "data_file.read"
line shouldn't compile if data_fetcher is unsigned char[].)
I haven't checked, but I have a feeling that this compiles in
VC++, possibly depending on compiler options.

I just checked, and it doesn't, at least with the options I use.
The obvious option to try would be treating 'char' as
unsigned. I haven't read this thread carefully enough to be
sure this is relevant - just a thought.
Does the standard really require "char" to be treated as a
separate type from "unsigned char"?

Yes, and it always has (from the early days of C, ever since
there's been an unsigned char).
My impression was that the signedness of "char" isn't
specified, and that types that are spelled differently but
have the same representation etc may or may not be treated as
distinct for overloading etc.

The standard defines a number of different types, and those
types are always different, regardless of whether their
representations are the same or not.
For example, on 32 bit platforms, "int" and "long int" are
IIRC sometimes distinct types for overloading and sometimes
not, depending on the compiler.

They are always distinct types for overloading purposes (and all
other purposes). They always have been (since the early days of
C), and I've never seen a compiler where this is not the case.
I would expect the same to apply to "char" and either "signed
char" or "unsigned char".

The same rules apply, but you've gotten the rules mixed up.
 
J

James Kanze

* Stephen Horne:
Possibly you've got this incorrect impression from standard
library types like 'size_t', which can be just 'typedef'
synonyms for other types.

Just a nit: not "can be", but "must be". Because it affects the
type system, both C and C++ are very specific as to whether a
type name is defined as a typedef or not. (They also differ in
this regard: in C, wchar_t is required to be a typedef, in C++,
it is not allowed to be a typedef, but must be a separate,
distinct type.)
 
A

Alf P. Steinbach

* James Kanze:
Just a nit: not "can be", but "must be".

I tried to be precise, in the sense of not disallowing e.g. size_t as a distinct
type, but evidently there's something I neither know nor am able to find.

Chapter & verse?

Because it affects the
type system, both C and C++ are very specific as to whether a
type name is defined as a typedef or not. (They also differ in
this regard: in C, wchar_t is required to be a typedef, in C++,
it is not allowed to be a typedef, but must be a separate,
distinct type.)

wchar_t must be a distinct type, yes, but wchar_t isn't a library type in C++.


- Alf
 
J

Jerry Coffin

* James Kanze:

I tried to be precise, in the sense of not disallowing e.g. size_t as a distinct
type, but evidently there's something I neither know nor am able to find.

Chapter & verse?

§18.1/3 says size_t is defined the same in C++ as in C. §6.5.3.4/4 of
the C standard says:

The value of the result is implementation-defined, and its
type (an unsigned integer type) is size_t, defined in
<stddef.h> (and other headers).

The phrase "an unsigned integer type" is not just saying that this is
an integer and it's unsigned. Rather, it's referring to the
definition of unsigned integers that's given in §6.2.5/6. This
specifies that the unsigned integer types are unsigned char, unsigned
short, unsigned int or unsigned long.

IOW, size_t must be one of those types, not some distinct type of its
own.

[Note: the section numbers I used are from the C99 standard -- my
copy of the C90 standard isn't handy at the moment. The section
numbers might be different in C90, but the general idea is the same;
I'm pretty sure the only relevant difference is that C99 adds
"unsigned long long" to the list of unsigned integer types.]
 
S

Stephen Horne

Yes, and it always has (from the early days of C, ever since
there's been an unsigned char).

But given that C doesn't have overloading, but does (of course) have
implicit conversions, the concept of distinct integer/character types
has always been very fuzzy in C. Basically, when does the C++ sense of
distinctness make any difference at all in C?

At one time, IIRC, it wasn't that usual for some "hackers" to have
parameter types that were completely different in the function
compared with the prototype. Even structs were sometimes declared
differently in different locations, though still being treated as the
same struct. The linker only cared about the function name, after all.
They are always distinct types for overloading purposes (and all
other purposes). They always have been (since the early days of
C), and I've never seen a compiler where this is not the case.

I thought you were just plain wrong about this, so I just tried
Borland C++ 5.02. Then Visual C++ 6. After trying CodeWarrior 5, I
figured I was getting a bit desperate ;-)

Guess you're right - other than the old non-strict-typing
do-I-really-care-what-the-exact-type-is fuzziness in C years ago,
combined with the very common use of alias types along the lines of
"INT32" etc tending to hide the real type, I'm not sure where my
misconception came from. Maybe it was a hangover from something that
happened during the 16-bit to 32-bit transition. Maybe it's just my
warped mind.
 
A

Alf P. Steinbach

* Jerry Coffin:
§18.1/3 says size_t is defined the same in C++ as in C. §6.5.3.4/4 of
the C standard says:

The value of the result is implementation-defined, and its
type (an unsigned integer type) is size_t, defined in
<stddef.h> (and other headers).

The phrase "an unsigned integer type" is not just saying that this is
an integer and it's unsigned. Rather, it's referring to the
definition of unsigned integers that's given in §6.2.5/6. This
specifies that the unsigned integer types are unsigned char, unsigned
short, unsigned int or unsigned long.
OK.


IOW, size_t must be one of those types, not some distinct type of its
own.

No, not at all, that's an incorrect conclusion.

By that logic a conforming C89 implementation is forbidden from offering a
64-bit unsigned integer type, unless its 'unsigned long' already fits the bill.

And e.g., by that logic there isn't much possible variability in implementing
[Note: the section numbers I used are from the C99 standard -- my
copy of the C90 standard isn't handy at the moment. The section
numbers might be different in C90, but the general idea is the same;
I'm pretty sure the only relevant difference is that C99 adds
"unsigned long long" to the list of unsigned integer types.]

OK.


Cheers,

- Alf
 
J

Jerry Coffin

* Jerry Coffin:

No, not at all, that's an incorrect conclusion.

By that logic a conforming C89 implementation is forbidden from offering a
64-bit unsigned integer type, unless its 'unsigned long' already fits the bill.

Not so -- it can offer some other type if it chooses to do so -- but
if it's not one of unsigned char, unsigned short, unsigned int or
unsigned long, it's not an "unsigned integer" type -- it's just
something that happens to act a whole lot like an integer.
And e.g., by that logic there isn't much possible variability in implementing
<stdint.h>. :)

As far as C89 cares, <stdint.h> simply doesn't exist, because it
wasn't added until C99.

Since they're not included in C89/95, neither <stdint.h> nor the
extended integer types "exist" from the viewpoint of C++ 98/03.
 
A

Alf P. Steinbach

* Jerry Coffin:
Not so -- it can offer some other type if it chooses to do so -- but
if it's not one of unsigned char, unsigned short, unsigned int or
unsigned long, it's not an "unsigned integer" type -- it's just
something that happens to act a whole lot like an integer.

You're saying a C89 compiler can't have 32-bit 'long' and 64-bit 'size_t'.

That would mean that there are /no/ conforming C89 compilers for 64-bit Windows,
where 'long' is 32 bits and 'size_t' is 64 bits.

I don't believe that.

As far as C89 cares, <stdint.h> simply doesn't exist, because it
wasn't added until C99.

Since they're not included in C89/95, neither <stdint.h> nor the
extended integer types "exist" from the viewpoint of C++ 98/03.

You quoted the C99 standard. Either your conclusion, which followed entirely
from a disingenious and fairly creative interpretation of that quote, does apply
to C99, or it doesn't, in which case it doesn't apply to C89 either. Choose.


Cheers & hth.,

- Alf
 
S

Stephen Horne

You're saying a C89 compiler can't have 32-bit 'long' and 64-bit 'size_t'.

This is a bloody stupid question, but I'm going to ask it anyway...

What if "long" is 32 bit, but "short" is 64 bit? Is that legal? Can
"size_t" be an alias of that 64-bit "short"?

ie is there a formal requirement that sizeof(long) >= sizeof (short)?
 
A

Alf P. Steinbach

* Stephen Horne:
This is a bloody stupid question, but I'm going to ask it anyway...

He he, there's no such thing as a stupid question about facts. :)

What if "long" is 32 bit, but "short" is 64 bit? Is that legal?
No.


Can "size_t" be an alias of that 64-bit "short"?

'size_t' can be an alias for any unsigned integer type sufficient to represent
the size of the largest possible object.

ie is there a formal requirement that sizeof(long) >= sizeof (short)?

Yes, it's been there since K&R C.


Cheers, & hth.,

- Alf
 
J

Jerry Coffin

sh006d3592 said:
This is a bloody stupid question, but I'm going to ask it anyway...

What if "long" is 32 bit, but "short" is 64 bit? Is that legal? Can
"size_t" be an alias of that 64-bit "short"?

ie is there a formal requirement that sizeof(long) >= sizeof (short)?

Yes, §3.9.1/a:

There are four signed integer types: ``signed char'',
``short int'', ``int'', and ``long int.'' In this list,
each type provides at least as much storage as those
preceding it in the list.

and §3.9.1/3:

For each of the signed integer types, there exists a
corresponding (but different) unsigned integer type:
``unsigned char'', ``unsigned short int'', ``unsigned
int'', and ``unsigned long int,'' each of which
occupies the same amount of storage and has the same
alignment requirements (3.9) as the corresponding
signed integer type.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,982
Messages
2,570,190
Members
46,736
Latest member
zacharyharris

Latest Threads

Top