Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

why unsigned char not work

4 views
Skip to first unread message

Mug

unread,
Jul 21, 2009, 11:26:31 AM7/21/09
to
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::out|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

Michael Doubez

unread,
Jul 21, 2009, 11:40:46 AM7/21/09
to
On 21 juil, 17:26, Mug <exallion.l...@gmail.com> wrote:
> 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::out|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]
);

--
Michael

Mug

unread,
Jul 21, 2009, 11:53:18 AM7/21/09
to
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 4294967235
> --
> Michael
thanks 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

James Kanze

unread,
Jul 22, 2009, 3:35:52 AM7/22/09
to
On Jul 21, 5:26 pm, Mug <exallion.l...@gmail.com> wrote:

> 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::out|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.

--
James Kanze (GABI Software) email:james...@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

James Kanze

unread,
Jul 22, 2009, 3:42:20 AM7/22/09
to

> > here's my program:

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[].)

> > 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 ?

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.

> > 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]
> );

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.

Stephen Horne

unread,
Jul 22, 2009, 1:35:24 PM7/22/09
to
On Wed, 22 Jul 2009 00:42:20 -0700 (PDT), James Kanze
<james...@gmail.com> wrote:

>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".

Alf P. Steinbach

unread,
Jul 22, 2009, 1:45:26 PM7/22/09
to
* 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

Jerry Coffin

unread,
Jul 22, 2009, 4:34:56 PM7/22/09
to
In article <ogie65hc6teln29sa...@4ax.com>, sh006d3592
@blueyonder.co.uk says...

[ ... ]

> 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.

--
Later,
Jerry.

Stephen Horne

unread,
Jul 22, 2009, 7:59:09 PM7/22/09
to
On Wed, 22 Jul 2009 19:45:26 +0200, "Alf P. Steinbach"
<al...@start.no> wrote:

>> 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.

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.

James Kanze

unread,
Jul 23, 2009, 5:01:03 AM7/23/09
to
On Jul 22, 7:35 pm, Stephen Horne <sh006d3...@blueyonder.co.uk> wrote:
> On Wed, 22 Jul 2009 00:42:20 -0700 (PDT), James Kanze

> <james.ka...@gmail.com> wrote:
> >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.

James Kanze

unread,
Jul 23, 2009, 5:03:27 AM7/23/09
to
On Jul 22, 7:45 pm, "Alf P. Steinbach" <al...@start.no> wrote:
> * 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.)

Alf P. Steinbach

unread,
Jul 23, 2009, 7:08:35 AM7/23/09
to
* James Kanze:

> On Jul 22, 7:45 pm, "Alf P. Steinbach" <al...@start.no> wrote:
>> * 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".

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

Jerry Coffin

unread,
Jul 23, 2009, 9:17:14 AM7/23/09
to
In article <h49gk8$fcv$1...@news.eternal-september.org>, al...@start.no
says...

>
> * James Kanze:
> > On Jul 22, 7:45 pm, "Alf P. Steinbach" <al...@start.no> wrote:
> >> * 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".
>
> 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.]

--
Later,
Jerry.

Stephen Horne

unread,
Jul 23, 2009, 10:19:28 AM7/23/09
to
On Thu, 23 Jul 2009 02:01:03 -0700 (PDT), James Kanze
<james...@gmail.com> wrote:

>On Jul 22, 7:35 pm, Stephen Horne <sh006d3...@blueyonder.co.uk> wrote:
>> On Wed, 22 Jul 2009 00:42:20 -0700 (PDT), James Kanze

>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.

Alf P. Steinbach

unread,
Jul 23, 2009, 3:13:13 PM7/23/09
to
* Jerry Coffin:

> In article <h49gk8$fcv$1...@news.eternal-september.org>, al...@start.no
> says...
>> * James Kanze:
>>> On Jul 22, 7:45 pm, "Alf P. Steinbach" <al...@start.no> wrote:
>>>> * 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".
>> 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.

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
<stdint.h>. :-)


> [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

Jerry Coffin

unread,
Jul 23, 2009, 5:18:08 PM7/23/09
to
In article <h4ad10$t1m$1...@news.eternal-september.org>, al...@start.no
says...

>
> * Jerry Coffin:
> > In article <h49gk8$fcv$1...@news.eternal-september.org>, al...@start.no
> > says...
> >> * James Kanze:
> >>> On Jul 22, 7:45 pm, "Alf P. Steinbach" <al...@start.no> wrote:
> >>>> * 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".
> >> 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.
>
> 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.

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.

--
Later,
Jerry.

Alf P. Steinbach

unread,
Jul 23, 2009, 6:54:10 PM7/23/09
to
* Jerry Coffin:
> In article <h4ad10$t1m$1...@news.eternal-september.org>, al...@start.no
> says...
>> * Jerry Coffin:
>>> In article <h49gk8$fcv$1...@news.eternal-september.org>, al...@start.no
>>> says...
>>>> * James Kanze:
>>>>> On Jul 22, 7:45 pm, "Alf P. Steinbach" <al...@start.no> wrote:
>>>>>> * 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".
>>>> 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.
>> 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.
>
> 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.


>> 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.

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.

Stephen Horne

unread,
Jul 23, 2009, 7:34:26 PM7/23/09
to
On Fri, 24 Jul 2009 00:54:10 +0200, "Alf P. Steinbach"
<al...@start.no> wrote:

>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)?

Alf P. Steinbach

unread,
Jul 23, 2009, 8:45:55 PM7/23/09
to
* Stephen Horne:

> On Fri, 24 Jul 2009 00:54:10 +0200, "Alf P. Steinbach"
> <al...@start.no> wrote:
>
>> 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...

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

Jerry Coffin

unread,
Jul 23, 2009, 9:40:53 PM7/23/09
to
In article <h4apvc$u4q$1...@news.eternal-september.org>, al...@start.no
says...

[ ... ]

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

Yes, that's correct. I'll even generalize that a bit: in C89, NO
integer type can be larger than long.



> 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.

Okay, I'll take your word for it.



> I don't believe that.

Why not?

> >> 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.
>
> 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.

My interpretation was neither creative nor disingenuous. The latter
borders on a direct accusation, for which I think you owe an apology.

As it happens, my interpretation also matches that the C Committee
used in their response to Defect Report #067. They were asked
essentially the same question being considered here, but in more
detail:

--------------quote-------------------
The terms ``signed integer type,'' ``unsigned integer type,'' and
``integral type'' are defined in subclause 6.1.2.5. The C Standard
also uses the terms ``integer type,'' ``signed integral type,'' and
``unsigned integral type'' without defining them. Integer-valued
bitfields are also introduced in subclause 6.5.2.

[ ... ]

c. Can an implementation extension add other types defined by the C
Standard to any of these six categories?
d. Can an implementation define other types (e.g. __very long) which
belong to any of these six categories?
e. If the answer to (c) or (d), or both, is yes, can size_t and
ptrdiff_t be one of these other types, or must it be a type in the
above list?
[ ... ]

Response

[ ...]
c) No, the list in the C Standard is meant to be exhaustive. For
example, float cannot be defined as an integer type.
d) No strictly conforming program could contain an instance of such a
type. The treatment of such types is beyond the scope of the C
Standard.
e) No, it must be a type in the list. For example, size_t cannot be
defined as unsigned __int24.
--------------end of quote-------------

That _changed_ in C99 though: along with adding the requirement for
long long (in both signed and unsigned variants, of course) C99
defines the listed types as the "standard integer types". It then
adds a completely new possibility: implementation defined "extended
integer types" -- and says the "integer types" are the union of the
standard integer types and the extended integer types (along with
other irrelevant types like _Bool).

--
Later,
Jerry.

Jerry Coffin

unread,
Jul 23, 2009, 9:40:52 PM7/23/09
to
In article <9jsh65l9qra48jta7...@4ax.com>, sh006d3592
@blueyonder.co.uk says...

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.

--
Later,
Jerry.

Alf P. Steinbach

unread,
Jul 23, 2009, 10:11:59 PM7/23/09
to
* Jerry Coffin:

That's interesting, in a sort of political way.

But it means that unless the C89 DR 67 resolution (wrong way, and thus fixed in
C99) was adopted in an intermediate official standard's technical corrigendum,
the C89 standard itself says no such thing.

If there was such a technical corrigendum, then there are no conforming 64-bit
Windows C89 compilers, and hence no conforming 64-bit Windows C++ compilers...

Anyway, regardless of the C comittee's goofup & subsequent correction in C99,
you can't rely on 'size_t' being one of the standard's built-in types (it's a
rather impotent standard that manages to not being implementable on one of the
major platforms, hence my use of the word "goofup", they really did :-) ).

64 bit Windows being the main example that I know, and the reason that I
intentionally left the door open for that. ;-)

Jerry Coffin

unread,
Jul 23, 2009, 10:33:02 PM7/23/09
to
In article <h4b5i8$c67$1...@news.eternal-september.org>, al...@start.no
says...

[ ... ]

> That's interesting, in a sort of political way.
>
> But it means that unless the C89 DR 67 resolution (wrong way, and thus fixed in
> C99) was adopted in an intermediate official standard's technical corrigendum,
> the C89 standard itself says no such thing.

Nonsense! Somebody asked some questions, claiming that there was a
defect in the standard. The Committee has three choices in such a
situation: 1) decide it's a defect, and fix it, or 2) decide it's a
defect, but fixing is beyond their current scope (e.g. won't be
considered until the next version of standard), or 3) decide it's not
a defect at all, and simply offer clarification of what the standard
requires.

In this case, they took the third route -- clarified what the
standard said. No change was made or needed, because the standard
already covered the situation. The C89 standard requires exactly what
I said, and the committee has provided a clarification that affirms
that beyond any reasonable misinterpretation or doubt.

--
Later,
Jerry.

Alf P. Steinbach

unread,
Jul 23, 2009, 10:49:09 PM7/23/09
to
* Jerry Coffin:

Yeah, that's interesting, in a sort of political way. :D

Alf P. Steinbach

unread,
Jul 23, 2009, 10:57:47 PM7/23/09
to
* Alf P. Steinbach:

Sorry, I didn't notice your snippage: it means that the C committe has decided
that C89 is not implementable on platforms such as 64-bit Windows.

And thus that it has decided, perhaps before that platform was conceived but it
does not matter, that all 64-bit Windows C89 compilers and C++ compilers, with
'size_t' 64 bit and 'long' 32 bit, are non-conforming, and thus made themselves
utterly irrelevant wrt. this question. :-)

It could be interesting to know exactly /when/ they goofed up in such a major
way (although corrected in C99) -- was it before or after the C++98 standard
was adopted?


Cheers,

- Alf

Bart van Ingen Schenau

unread,
Jul 24, 2009, 2:07:11 AM7/24/09
to
On Jul 24, 4:57 am, "Alf P. Steinbach" <al...@start.no> wrote:
> * Alf P. Steinbach:
> > * Jerry Coffin:
> >> In article <h4b5i8$c6...@news.eternal-september.org>, al...@start.no

> >> says...
>
> >> [ ... ]
>
> >>> That's interesting, in a sort of political way.
>
> >>> But it means that unless the C89 DR 67 resolution (wrong way, and
> >>> thus fixed in C99) was adopted in an intermediate official standard's
> >>> technical corrigendum, the C89 standard itself says no such thing.
>
> >> Nonsense! Somebody asked some questions, claiming that there was a
> >> defect in the standard. The Committee has three choices in such a
> >> situation: 1) decide it's a defect, and fix it, or 2) decide it's a
> >> defect, but fixing is beyond their current scope (e.g. won't be
> >> considered until the next version of standard), or 3) decide it's not
> >> a defect at all, and simply offer clarification of what the standard
> >> requires.
>
> >> In this case, they took the third route -- clarified what the standard
> >> said. No change was made or needed, because the standard already
> >> covered the situation. The C89 standard requires exactly what I said,
> >> and the committee has provided a clarification that affirms that
> >> beyond any reasonable misinterpretation or doubt.
>
> > Yeah, that's interesting, in a sort of political way. :D
>
> Sorry, I didn't notice your snippage: it means that the C committe has decided
> that C89 is not implementable on platforms such as 64-bit Windows.

No, you have that the wrong way around. Unless 64-bit Windows existed
when the C standard was drafted in 1989, it was Microsoft that decided
not to support the creation of conforming C89 implementations.

> And thus that it has decided, perhaps before that platform was conceived but it
> does not matter, that all 64-bit Windows C89 compilers and C++ compilers, with
> 'size_t' 64 bit and 'long' 32 bit, are non-conforming, and thus made themselves
> utterly irrelevant wrt. this question. :-)
>
> It could be interesting to know exactly /when/ they goofed up in such a major
> way (although corrected in C99)  --  was it before or after the C++98 standard
> was adopted?

As far as I can determine, the limitation of having only three integer
types has existed since K&R C, so way before the C++98 standard.
My copy of K&R2 (copyright 1988) states in Appendix A (Reference
Manual): "Besides the char types, up to three sizes of integer,
declared short int, int and long int, are available." [A4.2] There is
no annotation on the paragraph indicating that this has changed from
K&R1.

>
> Cheers,
>
> - Alf

Bart v Ingen Schenau

Alf P. Steinbach

unread,
Jul 24, 2009, 2:36:50 AM7/24/09
to
* Bart van Ingen Schenau:

Sorry, but that's completely meaningless. "platforms such as X" does not mean
"X". The committee goof-up that Jerry referred to most probably did not happen
in 1989, it most probably happened much later. And your conclusion about
Microsoft doesn't follow even from your very flawed premises. What you write is
just rubbish. Utterly. Get some coffee. Please.


>> And thus that it has decided, perhaps before that platform was conceived but it
>> does not matter, that all 64-bit Windows C89 compilers and C++ compilers, with
>> 'size_t' 64 bit and 'long' 32 bit, are non-conforming, and thus made themselves
>> utterly irrelevant wrt. this question. :-)
>>
>> It could be interesting to know exactly /when/ they goofed up in such a major
>> way (although corrected in C99) -- was it before or after the C++98 standard
>> was adopted?
>
> As far as I can determine, the limitation of having only three integer
> types has existed since K&R C, so way before the C++98 standard.

Sorry, but that trivia is some astronomical units beside the point discussed.


> My copy of K&R2 (copyright 1988) states in Appendix A (Reference
> Manual): "Besides the char types, up to three sizes of integer,
> declared short int, int and long int, are available." [A4.2] There is
> no annotation on the paragraph indicating that this has changed from
> K&R1.

My copy of K&R1 is from 1976, IIRC, but to the degree that what you're writing
has some meaning (I can sort of feel a tendency towards some kind of attempt at
taking an opposing view, sort of free-associating your way in that direction,
but it's very hard to grok) it's completely irrelevant to anything discussed.

Bo Persson

unread,
Jul 24, 2009, 5:29:25 AM7/24/09
to

I think it does. The way to get a conforming implementation is of
course to make long wide enough. Keeping both int and long 32 bits on
64 bit Windows was a Microsoft decision.

On the other hand, I don't think they claim strict C89 conformance
anyway, so they are saved by the new C99 wording.


Bo Persson


James Kanze

unread,
Jul 24, 2009, 5:35:33 AM7/24/09
to
On Jul 24, 12:54 am, "Alf P. Steinbach" <al...@start.no> wrote:
> * Jerry Coffin:
> > In article <h4ad10$t1...@news.eternal-september.org>, al...@start.no
> > says...
> >> * Jerry Coffin:
> >>> In article <h49gk8$fc...@news.eternal-september.org>, al...@start.no

> >>> says...
> >>>> * James Kanze:
> >>>>> On Jul 22, 7:45 pm, "Alf P. Steinbach" <al...@start.no> wrote:
> >>>>>> * 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".
> >>>> 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.
> >> 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.

It's what the C standard says, and has always said.

> >> 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.

Note that while the above is true for C++ (until C++0x is
formalized) and C90, it's not true for C99. C99 allows a system
to provide extended integer types as well. The names of such
extended integral types, however, may not impinge on the user's
namespace : something like __int64 or long long long would be
legal, but not size_t.

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

That's the situation. C90 and C++03 clearly says that there are
exactly four (no more, no less) unsigned integer types: unsigned
char, unsigned short, unsigned int and unsigned long.

> 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.

Read the standard.

It is an interesting point, however: it does mean that C++ isn't
implementable under 64 bit Windows.

> >> 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.

> 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.

The definition of size_t is identical in C90, C99 and C++03 (and
it won't change in C++0x): size_t must be a typedef (because
there's no other way to define an "integral type" in a header
file) to an unsigned integral type. C90 and C++03 limit
unsigned integral types to exactly four predefined types (in
§3.9.1/3 in C++03); C99 and C++0x allow an implementation to
define additional integral types, but do not allow the names of
these types to impinge on the user address space:

#include <stdio.h>

int main()
{
int size_t = 42 ;
printf( "%d\n", size_t ) ;
return 0 ;
}

is a perfectly legal C program, guaranteed to compile, run and
output 42. It's also a perfectly legal C++ program.

James Kanze

unread,
Jul 24, 2009, 5:51:03 AM7/24/09
to
On Jul 24, 4:11 am, "Alf P. Steinbach" <al...@start.no> wrote:
> * Jerry Coffin:
> > In article <h4apvc$u4...@news.eternal-september.org>, al...@start.no
> > says...

[...]

> > [ ... ]

> > Response

It's more than just political. It defines C (and indirectly
C++).

> But it means that unless the C89 DR 67 resolution (wrong way,
> and thus fixed in C99) was adopted in an intermediate official
> standard's technical corrigendum, the C89 standard itself says
> no such thing.

The committee's response to the DR was that there was no defect.
This is what the standard currently says. (IMHO, it says so
rather clearly, in fact. I don't see how it could be
interpreted otherwise.)

In C, the guarantee is a very important one (and was broken by
C99): if you wanted to output a size_t, you needed to do:

size_t x ;
printf( "%lu\n", (unsigned long)x ) ;

and you were guaranteed to get the actual value displayed.

There was actually a great deal of argument about this in the C
committee, when the extended types were introduced, because this
guarantee would be broken (and thus, a significant amount of
existing correct code would be broken). In the end, the
committee bit the bullet, and broke the code, but designed the
standard so that it should never be necessary to break code for
this reason again.

> If there was such a technical corrigendum, then there are no
> conforming 64-bit Windows C89 compilers, and hence no
> conforming 64-bit Windows C++ compilers...

Your comment is correct. Windows 64 bits is a platform on which
C++ cannot be implemented. It's also a platform on which many
existing, correct C90 programs will not work correctly.

> Anyway, regardless of the C comittee's goofup & subsequent
> correction in C99, you can't rely on 'size_t' being one of the
> standard's built-in types (it's a rather impotent standard
> that manages to not being implementable on one of the major
> platforms, hence my use of the word "goofup", they really did
> :-) ).

The goofup is on the part of Microsoft, not the C standard's
committee. It has long been an established and important
invariant in C that you could represent any unsigned integral
type as an unsigned long, and any signed integral type as a
signed long, without loss of value. Given the lack of type
safety in C (and in C++), you need some sort of guarantee along
these lines in order to write portable code. (There was a
goofup in the C standard committee in introducing long long, and
in allowing extended types wider than long. If more integral
types were needed---which they were---then they should be
required to be situated between char and long in size.)

> 64 bit Windows being the main example that I know, and the
> reason that I intentionally left the door open for that. ;-)

There's no logical requirement that long be a 32 bit type on a
64 bit machine. In fact, there's a logical requirement that it
be a 64 bit type. But of course, with enough market power, one
can ignore logical requirements.

James Kanze

unread,
Jul 24, 2009, 6:06:13 AM7/24/09
to
On Jul 24, 8:07 am, Bart van Ingen Schenau <b...@ingen.ddns.info>
wrote:

> On Jul 24, 4:57 am, "Alf P. Steinbach" <al...@start.no> wrote:

[...]


> > Sorry, I didn't notice your snippage: it means that the C
> > committe has decided that C89 is not implementable on
> > platforms such as 64-bit Windows.

> No, you have that the wrong way around. Unless 64-bit Windows
> existed when the C standard was drafted in 1989, it was
> Microsoft that decided not to support the creation of
> conforming C89 implementations.

It's actually a very serious goofup on the part of Microsoft,
since it breaks a lot of portably written C programs. In C++,
of course, function and operator overloading, templates and such
mean that it's less of a problem, but in C, if you want to
input or output a value, you absolutely have to know its real
(not typedef'ed) type. For things where you don't know the
actual type, like size_t, you have to have a "worst case" type,
or you can't write portable code. In C, the guaranteed "worst
case" type was long, until the vendors started breaking this
guarantee. (Microsoft wasn't the first---most of the Unix
platforms provided a "long long" well before. At least they
weren't stupid enough to typedef any "standard" type to it.)

> > And thus that it has decided, perhaps before that platform
> > was conceived but it does not matter, that all 64-bit
> > Windows C89 compilers and C++ compilers, with 'size_t' 64
> > bit and 'long' 32 bit, are non-conforming, and thus made
> > themselves utterly irrelevant wrt. this question. :-)

> > It could be interesting to know exactly /when/ they goofed
> > up in such a major way (although corrected in C99) -- was
> > it before or after the C++98 standard was adopted?

> As far as I can determine, the limitation of having only three
> integer types has existed since K&R C, so way before the C++98
> standard.

It's four, not three, and it's sizes of integral types, not
integral types. In fact, in C90, there are exactly nine
integral types: char, signed char, unsigned char, short,
unsigned short, int, unsigned int, long and unsigned long.
C++98 adds bool and wchar_t to this list. C99 added _Bool, long
long and unsigned long long, AND the possibility for an
implementation to add extended integral types.

There was a lot of argument about this change in C99; many
members of the committee opposed it because of the amount of
existing code it broke, and because it broke one of the most
basic guarantees C had always given---a guarantee which was
necessary and widely used in portable C.

James Kanze

unread,
Jul 24, 2009, 6:16:14 AM7/24/09
to
On Jul 23, 4:19 pm, Stephen Horne <sh006d3...@blueyonder.co.uk> wrote:
> On Thu, 23 Jul 2009 02:01:03 -0700 (PDT), James Kanze

> <james.ka...@gmail.com> wrote:
> >On Jul 22, 7:35 pm, Stephen Horne <sh006d3...@blueyonder.co.uk> wrote:
> >> On Wed, 22 Jul 2009 00:42:20 -0700 (PDT), James Kanze
> >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?

char* p ;
unsigned char* q = p ;

Illegal, and requires a diagnostic, both in C and 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.

Both C and C++ have a lot of undefined behavior. It's true that
because of overloading, declaring a function with different
parameters declares two different functions in C++, rather than
being undefined behavior as in C. And for historical reasons, C
also allows declaring functions without providing any
information with regards to the parameters the function takes;
as long as the function is actually called with the correct
types (no coercion will be done by the compiler, of course), the
program is correct. C also uses a different definition of
structure equivalence, such that:
struct { int a; int b; } ;
is the same type in all translation units (where as in C++, it
is a type not known outside of the scope where the declaration
occurs).

There are also a number of smaller differences: C defines a
notion of compatible type, which C++ doesn't (but C++ has a
couple of very special rules to allow most well written C to
compile anyway). But basically, if you write:
struct S { double a ; } ;
void f( S* p ) ;
in one file, and:
struct S { unsigned short a[ 4 ] ; } ;
void f( S* p ) { /* ... */ }
in another, it's undefined behavior, in both languages.

Jerry Coffin

unread,
Jul 24, 2009, 10:12:50 AM7/24/09
to
In article <71a838a8-a116-4ce4-b309-43555a6bd406
@h31g2000yqd.googlegroups.com>, james...@gmail.com says...

[ ... ]

> It is an interesting point, however: it does mean that C++ isn't
> implementable under 64 bit Windows.

It doesn't mean anything of the sort. The current implementations may
not conform, but that's completely different from it being impossible
to create an implementation that does conform. Just for example, they
could have 8-bit char, 16-bit short, 32-bit int, 64-bit long, and
size_t a typedef for long.

In most implementations int is the same size as either short or long
-- but that is NOT a requirement.

--
Later,
Jerry.

Alf P. Steinbach

unread,
Jul 24, 2009, 12:16:49 PM7/24/09
to
* Jerry Coffin:

> In article <71a838a8-a116-4ce4-b309-43555a6bd406
> @h31g2000yqd.googlegroups.com>, james...@gmail.com says...
>
> [ ... ]
>
>> It is an interesting point, however: it does mean that C++ isn't
>> implementable under 64 bit Windows.
>
> It doesn't mean anything of the sort. The current implementations may
> not conform, but that's completely different from it being impossible
> to create an implementation that does conform. Just for example, they
> could have 8-bit char, 16-bit short, 32-bit int, 64-bit long, and
> size_t a typedef for long.

You can't sell such a compiler, since source code using any API won't be correct.

Please understand that with standardization we're talking about supporting the
real world.

"Impossible" does not refer to abstract formalism, it refers to the real world.

Alf P. Steinbach

unread,
Jul 24, 2009, 12:20:51 PM7/24/09
to
* James Kanze:

The exact same wording is interpreted differently in C99, it's rather easy. :-)

And the interpretation is a made-up one, since it out of the blue assigns a very
special and unreasonable meaning (nowhere defined) to a very ordinary term.

In short the C committee screwed up by its resolution of the Defect Report, but
got back on track with C99 (realizing its fundamental screw-up), that's all. ;-)


Cheers,

- Alf

Stephen Horne

unread,
Jul 24, 2009, 12:48:08 PM7/24/09
to
On Fri, 24 Jul 2009 03:16:14 -0700 (PDT), James Kanze
<james...@gmail.com> wrote:

>On Jul 23, 4:19 pm, Stephen Horne <sh006d3...@blueyonder.co.uk> wrote:
>> On Thu, 23 Jul 2009 02:01:03 -0700 (PDT), James Kanze
>
>> <james.ka...@gmail.com> wrote:
>> >On Jul 22, 7:35 pm, Stephen Horne <sh006d3...@blueyonder.co.uk> wrote:
>> >> On Wed, 22 Jul 2009 00:42:20 -0700 (PDT), James Kanze
>> >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?
>
> char* p ;
> unsigned char* q = p ;
>
>Illegal, and requires a diagnostic, both in C and in C++.

Obviously, I've been focussing so much on overloading that I've been a
bit stupid, and even forgotten where this thread started. Whoops.

Stephen Horne

unread,
Jul 24, 2009, 1:16:13 PM7/24/09
to
On Fri, 24 Jul 2009 11:29:25 +0200, "Bo Persson" <b...@gmb.dk> wrote:

>I think it does. The way to get a conforming implementation is of
>course to make long wide enough. Keeping both int and long 32 bits on
>64 bit Windows was a Microsoft decision.

I would have thought they could equally have kept long as 32 bits, but
also have kept size_t as 32 bits. They could still have a 64 bit
integer type, it just wouldn't be an "integer type" in the
standard-defined sense.

Borland C++ 5.02 had 64-bit integer types. They just weren't integer
types in the C89-standard-defined sense - BC++ kept size_t as 32 bit.
Change the back end to one that generates 64-bit executables and the C
support would presumably have been C89 compliant (in this respect),
yet targetting a 64-bit platform.

Basically, you can have a C89-compliant compiler for any 64 bit
platform by keeping all behaviour as it was for a C89-compiler for a
32 bit plaform. You either keep 32 bit limits, or you use work around
them using language extensions. That's how we got 32 bit support in
the days when standard pointer types on DOS compilers were all 16 bit
- remember far pointers? Yuck, yes, but it's possible.

I'm assuming pointers would have to be 32 bits to due to ptrdiff_t,
but I don't think that was defined in C89 anyway - the limits may only
need to apply to integers.

Jerry Coffin

unread,
Jul 24, 2009, 1:39:55 PM7/24/09
to
In article <6kpj65hm7inpi2l31...@4ax.com>, sh006d3592
@blueyonder.co.uk says...

>
> On Fri, 24 Jul 2009 11:29:25 +0200, "Bo Persson" <b...@gmb.dk> wrote:
>
> >I think it does. The way to get a conforming implementation is of
> >course to make long wide enough. Keeping both int and long 32 bits on
> >64 bit Windows was a Microsoft decision.
>
> I would have thought they could equally have kept long as 32 bits, but
> also have kept size_t as 32 bits. They could still have a 64 bit
> integer type, it just wouldn't be an "integer type" in the
> standard-defined sense.

That would work too, but would lose most of the advantages of 64-bit
code, especially direct access to more than 4 GiB of memory. In fact,
they've had exactly that situation with their 32-bit compiler for
years -- an __int64 type in addition to the standard integer types.

You do still run into a few obvious problems with that. For example,
though it's hard to call it a binding requirement, there is language
in the standard saying that int should be the size suggested by the
architecture -- and it's at least open to argument that on 64-bit
Windows, that should be a 64-bit type (and yes, the solution I posted
earlier had exactly the same shortcoming).

--
Later,
Jerry.

Stephen Horne

unread,
Jul 24, 2009, 1:50:00 PM7/24/09
to
On Fri, 24 Jul 2009 18:16:49 +0200, "Alf P. Steinbach"
<al...@start.no> wrote:

>You can't sell such a compiler, since source code using any API won't be correct.

You package it with an API-wrapper that presents a C89-compliant
interface such as, for example, one that gives source-level Win32
compatibility plus a few extensions. If someone is really that
desperate for a C89-compliant compiler on 64 bit Windows, thats
probably exactly what they need.

Failing that, there's a surprising amount of command-line apps out
there - some people only need the standard libraries.

Alf P. Steinbach

unread,
Jul 24, 2009, 2:02:39 PM7/24/09
to
* Stephen Horne:

> On Fri, 24 Jul 2009 18:16:49 +0200, "Alf P. Steinbach"
> <al...@start.no> wrote:
>
>> You can't sell such a compiler, since source code using any API won't be correct.
>
> You package it with an API-wrapper that presents a C89-compliant
> interface such as, for example, one that gives source-level Win32
> compatibility plus a few extensions.

He he.

Have you considered such things as documentation, the constant stream of new
APIs from Microsoft, etc.?

Good luck.


> If someone is really that
> desperate for a C89-compliant compiler on 64 bit Windows, thats
> probably exactly what they need.

It opposite: no one, except some participants in this discussion, is paying the
slightest attention to the C committee's resolution of the DR, and that in
particular means that no compiler vendor is paying attention to the committee's
earlier (before C99) completely at-odds-with-reality stand. ;-)


> Failing that, there's a surprising amount of command-line apps out
> there - some people only need the standard libraries.

Again, good luck. :-)

Stephen Horne

unread,
Jul 24, 2009, 2:15:09 PM7/24/09
to
On Fri, 24 Jul 2009 11:39:55 -0600, Jerry Coffin
<jerryv...@yahoo.com> wrote:

>That would work too, but would lose most of the advantages of 64-bit
>code, especially direct access to more than 4 GiB of memory.

I'm not so sure that's as big an advantage as people think. Those
applications that need more than 4GB memory could probably work with
segmented memory quite easily. It's nowhere near as evil as back in
the days when a segment was 64K.

When weighed against all those compatibility issues hidden in old
libraries (pointers casted to/from that UINT32 type-alias, etc)...

>You do still run into a few obvious problems with that. For example,
>though it's hard to call it a binding requirement, there is language
>in the standard saying that int should be the size suggested by the
>architecture -- and it's at least open to argument that on 64-bit
>Windows, that should be a 64-bit type (and yes, the solution I posted
>earlier had exactly the same shortcoming).

Nah - the instruction set still comes in 8-bit chunks, I suspect, so
int should be 8 bits ;-)

The old how-many-bits-is-the-architecture hasn't had a simple answer
for a long time. Data register size doesn't match addressing width,
which doesn't match instruction granularity, which doesn't match bus
width...

Stephen Horne

unread,
Jul 24, 2009, 2:19:01 PM7/24/09
to
On Fri, 24 Jul 2009 20:02:39 +0200, "Alf P. Steinbach"
<al...@start.no> wrote:

>* Stephen Horne:
>> On Fri, 24 Jul 2009 18:16:49 +0200, "Alf P. Steinbach"
>> <al...@start.no> wrote:
>>
>>> You can't sell such a compiler, since source code using any API won't be correct.
>>
>> You package it with an API-wrapper that presents a C89-compliant
>> interface such as, for example, one that gives source-level Win32
>> compatibility plus a few extensions.
>
>He he.
>
>Have you considered such things as documentation, the constant stream of new
>APIs from Microsoft, etc.?
>
>Good luck.

1. I wasn't volunteering.
2. The whole point of the API wrapper I was suggesting was to support
the old API - not a whole stream of new ones.
3. As for documentation, if its compatible with Win32, you only need
to document the extensions.

Paul Brettschneider

unread,
Jul 24, 2009, 7:03:10 PM7/24/09
to
Alf P. Steinbach wrote:

FWIW, on other platforms - in the real world - "correct" behaviour is
possible. To me this looks like a bug of the windows platform. long
has been the longest word that fits into a register on every platform I've
seen so far. I cannot imagine why you would break this (unwritten) rule.

#include <iostream>
#define X(T) "sizeof("#T")=" << sizeof(T) << '\n'
int main()
{
std::cout << X(short)
<< X(int)
<< X(long)
<< X(long long)
<< X(size_t);

}

sizeof(short)=2
sizeof(int)=4
sizeof(long)=8
sizeof(long long)=8
sizeof(size_t)=8

Ian Collins

unread,
Jul 24, 2009, 7:06:58 PM7/24/09
to
Paul Brettschneider wrote:
> Alf P. Steinbach wrote:
>
>> * Jerry Coffin:
>>> In article <71a838a8-a116-4ce4-b309-43555a6bd406
>>> @h31g2000yqd.googlegroups.com>, james...@gmail.com says...
>>>
>>> [ ... ]
>>>
>>>> It is an interesting point, however: it does mean that C++ isn't
>>>> implementable under 64 bit Windows.
>>> It doesn't mean anything of the sort. The current implementations may
>>> not conform, but that's completely different from it being impossible
>>> to create an implementation that does conform. Just for example, they
>>> could have 8-bit char, 16-bit short, 32-bit int, 64-bit long, and
>>> size_t a typedef for long.
>> You can't sell such a compiler, since source code using any API won't be
>> correct.
>>
>> Please understand that with standardization we're talking about supporting
>> the real world.
>>
>> "Impossible" does not refer to abstract formalism, it refers to the real
>> world.
>
> FWIW, on other platforms - in the real world - "correct" behaviour is
> possible. To me this looks like a bug of the windows platform. long
> has been the longest word that fits into a register on every platform I've
> seen so far. I cannot imagine why you would break this (unwritten) rule.

Too much code based on bad assumptions?

--
Ian Collins

Paul Brettschneider

unread,
Jul 24, 2009, 7:26:05 PM7/24/09
to
Ian Collins wrote:

Yes, the reasoning must be something like that.
But since x86-64 is not binary compatible with x86 and you have to recompile
in any case, the sensible thing would have been to provide a 64 bit version
of the platform API where long is really long (i.e. 64 bit). Problematic
code assuming that sizeof(long)=4 is probably only found in some low level
communication code and that is a bug that needs to be fixed anyway.
Then, maybe I'm just too naive for the real world. ;)

Ian Collins

unread,
Jul 24, 2009, 7:38:12 PM7/24/09
to

You and the designers of every other popular OS!

--
Ian Collins

Paavo Helde

unread,
Jul 25, 2009, 2:28:16 AM7/25/09
to
Paul Brettschneider <paul.bret...@yahoo.fr> kirjutas:

From http://msdn.microsoft.com/en-us/library/cc953fe1.aspx there are some
interesting points. First, they announce that by the standard
restrictions (independent of Microsoft):

"long long: Larger than an unsigned long."

This would of course prevent making them same size. Next they go and
standardize for Microsoft C++:

"long, unsigned long: 4 bytes"
"long long: Equivalent to __int64."

Paavo

Ian Collins

unread,
Jul 25, 2009, 2:57:48 AM7/25/09
to
Paavo Helde wrote:
>
> From http://msdn.microsoft.com/en-us/library/cc953fe1.aspx there are some
> interesting points. First, they announce that by the standard
> restrictions (independent of Microsoft):
>
> "long long: Larger than an unsigned long."

Where do they get that from? long long isn't even part of the (current)
C++ standard. C99 makes no such statement about the relative size of
unsigned long and long long.

--
Ian Collins

James Kanze

unread,
Jul 25, 2009, 4:43:33 AM7/25/09
to
On Jul 24, 6:16 pm, "Alf P. Steinbach" <al...@start.no> wrote:
> * Jerry Coffin:

> > In article <71a838a8-a116-4ce4-b309-43555a6bd406
> > @h31g2000yqd.googlegroups.com>, james.ka...@gmail.com says...

> > [ ... ]

> >> It is an interesting point, however: it does mean that C++
> >> isn't implementable under 64 bit Windows.

> > It doesn't mean anything of the sort. The current
> > implementations may not conform, but that's completely
> > different from it being impossible to create an
> > implementation that does conform. Just for example, they
> > could have 8-bit char, 16-bit short, 32-bit int, 64-bit
> > long, and size_t a typedef for long.

> You can't sell such a compiler, since source code using any
> API won't be correct.

That's the problem. Since the system API is C (with no type
checking), you could, of course, retap all of the system
headers, replacing "long" with "int" in them. But that still
leaves the problem of third party software.

> Please understand that with standardization we're talking
> about supporting the real world.

Please understand that in this case, the standardization
preceded the "real world" by a couple of decades. Microsoft
made the decision to design their API's in such a way as to make
it impossible to implement a conforming C or C++ compiler on
them. C99 and C++0x contain changes that will make it possible.

James Kanze

unread,
Jul 25, 2009, 4:46:07 AM7/25/09
to
On Jul 24, 8:02 pm, "Alf P. Steinbach" <al...@start.no> wrote:
> * Stephen Horne:

[...]


> It opposite: no one, except some participants in this
> discussion, is paying the slightest attention to the C
> committee's resolution of the DR, and that in particular means
> that no compiler vendor is paying attention to the committee's
> earlier (before C99) completely at-odds-with-reality stand.
> ;-)

Commercially, the compiler vendors don't really have a choice.
If you can't implement a compliant compiler on the platform, you
can't deliver one, and the market says you must deliver
something.

In the mean time, of course, the lack of compliance means that a
lot of existing, working C programs fail on that platform.

Bo Persson

unread,
Jul 25, 2009, 6:37:49 AM7/25/09
to

The assumption was that as long has always been 32 bits on
DOS/Windows, too much of the code depends on that. Perhaps they did
evaluate their own code base? :-)

That the rest of us assume that long is the widest integer type,
seemed to be less important.


Bo Persson


Pete Becker

unread,
Jul 25, 2009, 9:19:14 AM7/25/09
to
Paavo Helde wrote:
>
> From http://msdn.microsoft.com/en-us/library/cc953fe1.aspx there are some
> interesting points. First, they announce that by the standard
> restrictions (independent of Microsoft):
>
> "long long: Larger than an unsigned long."
>

However, that's wrong. The requirement in C++0x is that long long must
provide at least as much storage as long, and that unsigned long long
must occupy the same amount of storage as long long.

--
Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of
"The Standard C++ Library Extensions: a Tutorial and Reference"
(www.petebecker.com/tr1book)

0 new messages