Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #91404 > unrolled thread

Re: unsigned int

Started by"Osmium" <r124c4u102@comcast.net>
First post2016-07-31 12:40 -0500
Last post2016-08-01 23:01 +0200
Articles 20 on this page of 27 — 7 participants

Back to article view | Back to comp.lang.c

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  Re: unsigned int "Osmium" <r124c4u102@comcast.net> - 2016-07-31 12:40 -0500
    Re: unsigned int David Brown <david.brown@hesbynett.no> - 2016-08-01 11:01 +0200
      Re: unsigned int James Kuyper <jameskuyper@verizon.net> - 2016-08-01 10:15 -0400
      Re: unsigned int Les Cargill <lcargill99@comcast.com> - 2016-08-01 09:59 -0500
        Re: unsigned int David Brown <david.brown@hesbynett.no> - 2016-08-01 17:21 +0200
          Re: unsigned int Keith Thompson <kst-u@mib.org> - 2016-08-01 09:55 -0700
            Re: unsigned int David Brown <david.brown@hesbynett.no> - 2016-08-01 22:42 +0200
              Re: unsigned int supercat@casperkitty.com - 2016-08-01 14:18 -0700
          Re: unsigned int Les Cargill <lcargill99@comcast.com> - 2016-08-01 13:11 -0500
            Re: unsigned int Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-08-01 19:46 +0100
              Re: unsigned int Les Cargill <lcargill99@comcast.com> - 2016-08-01 18:20 -0500
                Re: unsigned int David Brown <david.brown@hesbynett.no> - 2016-08-02 10:18 +0200
                  Re: unsigned int Les Cargill <lcargill99@comcast.com> - 2016-08-02 09:35 -0500
                    Re: unsigned int Keith Thompson <kst-u@mib.org> - 2016-08-02 08:00 -0700
                      Re: unsigned int Les Cargill <lcargill99@comcast.com> - 2016-08-02 11:12 -0500
                    Re: unsigned int David Brown <david.brown@hesbynett.no> - 2016-08-02 17:11 +0200
                      Re: unsigned int Les Cargill <lcargill99@comcast.com> - 2016-08-02 11:55 -0500
                        Re: unsigned int supercat@casperkitty.com - 2016-08-02 10:16 -0700
                          Re: unsigned int David Brown <david.brown@hesbynett.no> - 2016-08-03 14:02 +0200
                            Re: unsigned int Keith Thompson <kst-u@mib.org> - 2016-08-03 08:58 -0700
                        Re: unsigned int James Kuyper <jameskuyper@verizon.net> - 2016-08-02 13:57 -0400
                        Re: unsigned int Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-08-02 19:30 +0100
                        Re: unsigned int Keith Thompson <kst-u@mib.org> - 2016-08-02 11:38 -0700
                          Re: unsigned int David Brown <david.brown@hesbynett.no> - 2016-08-03 14:12 +0200
                        Re: unsigned int David Brown <david.brown@hesbynett.no> - 2016-08-03 13:45 +0200
            Re: unsigned int Keith Thompson <kst-u@mib.org> - 2016-08-01 12:02 -0700
              Re: unsigned int David Brown <david.brown@hesbynett.no> - 2016-08-01 23:01 +0200

Page 1 of 2  [1] 2  Next page →


#91404 — Re: unsigned int

From"Osmium" <r124c4u102@comcast.net>
Date2016-07-31 12:40 -0500
SubjectRe: unsigned int
Message-ID<e06rglFmcd5U1@mid.individual.net>
"Stefan Ram" wrote:

>  I am now trying to write a new lesson for my German-language
>  C course. This time about »unsigned« (say, »unsigned int«,
>  for a start).
>
>  So, what are the crucial facts the readers need to know?
>
>  Some things that come to my mind right now ("brainstorming"):
>
> - unsigned has defined semantics on overflow and underflow
>
> - comparisons like »<« can give unexpected results (I need
>  to figure out the possible cases where this can happen,
>  maybe you have such a case handy?)
>
> - there are suffixes for numerals to mark them as usigned,
>  like »u«
>
> - But sometimes, the type of a numeral that is not marked
>  with a suffix but is too large to be an int is »unsigned«?
>  (But this has changed between several standards? Or was
>  this in C++?)
>
> - A special conversion specification has to be used for
>  printf (scanf will only be treated later in the course)
>
> - there are the usual macros in <limits.h> for »unsigned int«.
>
> - I don't actually know the semantics for conversions
>  between signed and unsigned, but I think a can look them
>  up in the standard.
>
> - what did I miss? (Especially with regard to common errors
>  commited when using »unsigned«.)

A novice would naturally think that char was signed by default, the same as 
an int.  It is not, the default is chosen by the compiler writer.  Among 
other things, this has ramifications in bit shifting within characters,. 

[toc] | [next] | [standalone]


#91460

FromDavid Brown <david.brown@hesbynett.no>
Date2016-08-01 11:01 +0200
Message-ID<nnn35u$2dd$1@dont-email.me>
In reply to#91404
On 31/07/16 19:40, Osmium wrote:

> 
> A novice would naturally think that char was signed by default, the same
> as an int.  It is not, the default is chosen by the compiler writer. 
> Among other things, this has ramifications in bit shifting within
> characters,.

A novice may equally well think that a char was /unsigned/ by default,
since the obvious interpretation of "char" is "character", such as
letters, digits, etc. - and the concept of a "negative character" is
totally meaningless.

Clearly, assuming that "char" is unsigned by default is just as bad as
assuming it is signed by default.  In any situation where you use char
types to store numbers or whenever the signedness of char matters, you
should be explicit about it.

Since this is in the context of teaching C, I think programmers should
be strongly encouraged not to consider "char" for arithmetic at all -
including bit shifting (what does it mean to bit-shift a "z"
character?).  They should be encouraged to use "uint8_t" and "int8_t" as
appropriate.

I know there are targets that don't support uint8_t or int8_t.  But
these are few and far between these days, and mostly for rather
specialised programming.  People should be taught that such systems
exist, but for most programming tasks you can freely use uint8_t and
friends if that is what makes your code clearer and more sensible.

And with bit shifts in particular, people should be taught to stick to
unsigned types when doing bit manipulation.  It is almost always the
type you want, and you run far less risk of accidentally getting
undefined behaviour.

[toc] | [prev] | [next] | [standalone]


#91477

FromJames Kuyper <jameskuyper@verizon.net>
Date2016-08-01 10:15 -0400
Message-ID<nnnlif$sqs$1@dont-email.me>
In reply to#91460
On 08/01/2016 05:01 AM, David Brown wrote:
> On 31/07/16 19:40, Osmium wrote:
> 
>>
>> A novice would naturally think that char was signed by default, the same
>> as an int.  It is not, the default is chosen by the compiler writer. 
>> Among other things, this has ramifications in bit shifting within
>> characters,.
> 
> A novice may equally well think that a char was /unsigned/ by default,
> since the obvious interpretation of "char" is "character", such as
> letters, digits, etc. - and the concept of a "negative character" is
> totally meaningless.

Contrasting those two statements helps explain why implementations where
char was signed and ones where it was unsigned have co-existed since
long before the language was first standardized. That, in turn, explains
why the standard permits both possibilities.

[toc] | [prev] | [next] | [standalone]


#91484

FromLes Cargill <lcargill99@comcast.com>
Date2016-08-01 09:59 -0500
Message-ID<nnnnqr$589$1@dont-email.me>
In reply to#91460
David Brown wrote:
> On 31/07/16 19:40, Osmium wrote:
>
>>
>> A novice would naturally think that char was signed by default, the same
>> as an int.  It is not, the default is chosen by the compiler writer.
>> Among other things, this has ramifications in bit shifting within
>> characters,.
>
> A novice may equally well think that a char was /unsigned/ by default,
> since the obvious interpretation of "char" is "character", such as
> letters, digits, etc. - and the concept of a "negative character" is
> totally meaningless.
>


So then they must learn that a char is a specialization of an int. And
ints default to signed because the integers are both negative and 
positive in mathematics.

> Clearly, assuming that "char" is unsigned by default is just as bad as
> assuming it is signed by default.  In any situation where you use char
> types to store numbers or whenever the signedness of char matters, you
> should be explicit about it.
>

The present state of 'C' is arguably the least bad alternative. Most
problems in computing involve people complaining about default behavior
of systems that must serve many user bases, each of which needs its own
default behavior.


> Since this is in the context of teaching C, I think programmers should
> be strongly encouraged not to consider "char" for arithmetic at all -
> including bit shifting (what does it mean to bit-shift a "z"
> character?).  They should be encouraged to use "uint8_t" and "int8_t" as
> appropriate.
>

And this is all fine until you port to C++ and use -Wall on certain 
toolchains. :)

> I know there are targets that don't support uint8_t or int8_t.  But
> these are few and far between these days, and mostly for rather
> specialised programming.

Most programming is highly specialized these days.

> People should be taught that such systems
> exist, but for most programming tasks you can freely use uint8_t and
> friends if that is what makes your code clearer and more sensible.
>
> And with bit shifts in particular, people should be taught to stick to
> unsigned types when doing bit manipulation.  It is almost always the
> type you want, and you run far less risk of accidentally getting
> undefined behaviour.
>


-- 
Les Cargill

[toc] | [prev] | [next] | [standalone]


#91490

FromDavid Brown <david.brown@hesbynett.no>
Date2016-08-01 17:21 +0200
Message-ID<nnnpdf$b3s$1@dont-email.me>
In reply to#91484
On 01/08/16 16:59, Les Cargill wrote:
> David Brown wrote:
>> On 31/07/16 19:40, Osmium wrote:
>>
>>>
>>> A novice would naturally think that char was signed by default, the same
>>> as an int.  It is not, the default is chosen by the compiler writer.
>>> Among other things, this has ramifications in bit shifting within
>>> characters,.
>>
>> A novice may equally well think that a char was /unsigned/ by default,
>> since the obvious interpretation of "char" is "character", such as
>> letters, digits, etc. - and the concept of a "negative character" is
>> totally meaningless.
>>
> 
> 
> So then they must learn that a char is a specialization of an int. And
> ints default to signed because the integers are both negative and
> positive in mathematics.

But "char" is not a "specialisation of an int" in C - they have
different properties, and neither is a subset of the other.  And while
"int" is signed in C, "char" is not necessarily signed.

And the reason C's most common type, "int", is signed is because that is
a practical and useful feature for a type in programming - not because
integers are signed in mathematics.  C "int" and mathematical integers
are different things.

> 
>> Clearly, assuming that "char" is unsigned by default is just as bad as
>> assuming it is signed by default.  In any situation where you use char
>> types to store numbers or whenever the signedness of char matters, you
>> should be explicit about it.
>>
> 
> The present state of 'C' is arguably the least bad alternative. Most
> problems in computing involve people complaining about default behavior
> of systems that must serve many user bases, each of which needs its own
> default behavior.

Personally, I would rather have have a selection of byte-sized types in
a language like C.  I would like a type "char" which can hold character
data such as 'a'.  But assigning an integer value to a char (without
appropriate casts) should be an error.  I would like a type "byte" which
represents raw data in memory - "byte *" would be used instead of "void
*" in C, and also in many cases where "char *" is used.  So functions
like "memcpy" would deal in "byte*" pointers, "malloc" would return a
"byte*", but "strcpy" would use "char*" pointers.  And I would like
numerical types of byte size.  To fit C practice, these might be "signed
short short int" and "unsigned short short int" (with "signed" being the
default), though I am sure some people would object to those names.

But we have what we have in C - it's not going to change.  The best we
can do is write code in a way that minimises the risk of errors - and
that includes being explicit about using signed or unsigned char when
using them for numbers.

> 
> 
>> Since this is in the context of teaching C, I think programmers should
>> be strongly encouraged not to consider "char" for arithmetic at all -
>> including bit shifting (what does it mean to bit-shift a "z"
>> character?).  They should be encouraged to use "uint8_t" and "int8_t" as
>> appropriate.
>>
> 
> And this is all fine until you port to C++ and use -Wall on certain
> toolchains. :)

Why is that a problem?  And more particularly, why would it be a problem
if you use "uint8_t" and "int8_t" but not a problem when you use "char",
"signed char" and "unsigned char"?

(Again, this is assuming that uint8_t and int8_t exist on that target.)

> 
>> I know there are targets that don't support uint8_t or int8_t.  But
>> these are few and far between these days, and mostly for rather
>> specialised programming.
> 
> Most programming is highly specialized these days.

Most programming is not for DSPs or dinosaur mainframes.  The
programming domain may be specialised, but it will very rarely need to
run on targets with CHAR_BIT != 8.  So if the using of uint8_t and
int8_t makes code clearer, simpler, more efficient, or easier to
maintain, then I believe those types should be used freely in most cases.

One should, of course, rely on CHAR_BIT == 8 without ensuring a clear
compile-time failure if that is not the case.  That might be done by
testing CHAR_BIT and issuing a #error directive - but IMHO it is good
enough to simply make use of uint8_t and int8_t types.

> 
>> People should be taught that such systems
>> exist, but for most programming tasks you can freely use uint8_t and
>> friends if that is what makes your code clearer and more sensible.
>>
>> And with bit shifts in particular, people should be taught to stick to
>> unsigned types when doing bit manipulation.  It is almost always the
>> type you want, and you run far less risk of accidentally getting
>> undefined behaviour.
>>
> 
> 

[toc] | [prev] | [next] | [standalone]


#91500

FromKeith Thompson <kst-u@mib.org>
Date2016-08-01 09:55 -0700
Message-ID<ln60rk5szm.fsf@kst-u.example.com>
In reply to#91490
David Brown <david.brown@hesbynett.no> writes:
[...]
> Personally, I would rather have have a selection of byte-sized types in
> a language like C.  I would like a type "char" which can hold character
> data such as 'a'.  But assigning an integer value to a char (without
> appropriate casts) should be an error.  I would like a type "byte" which
> represents raw data in memory - "byte *" would be used instead of "void
> *" in C, and also in many cases where "char *" is used.  So functions
> like "memcpy" would deal in "byte*" pointers, "malloc" would return a
> "byte*", but "strcpy" would use "char*" pointers.  And I would like
> numerical types of byte size.  To fit C practice, these might be "signed
> short short int" and "unsigned short short int" (with "signed" being the
> default), though I am sure some people would object to those names.

Apart from the implicit conversion of numeric type to char, that's
pretty much what we have.  `char` is the type for (narrow) characters,
`unsigned char` represents raw data, and `signed char` is a narrow
signed integer type.

> But we have what we have in C - it's not going to change.  The best we
> can do is write code in a way that minimises the risk of errors - and
> that includes being explicit about using signed or unsigned char when
> using them for numbers.

Agreed.

As for uint8_t and int8_t, you should use those only if you need
*exactly* 8 bits.  If you just want a narrow integer type of *at least*
8 bits, you can use unsigned char and signed char -- or
[u]int_(least|fast)8_t, depending on your requirements.

[...]

> One should, of course, rely on CHAR_BIT == 8 without ensuring a clear
> compile-time failure if that is not the case.  That might be done by
> testing CHAR_BIT and issuing a #error directive - but IMHO it is good
> enough to simply make use of uint8_t and int8_t types.

I presume you omitted a "not" there.

On the other hand, it's reasonable to assume CHAR_BIT == 8 if your code
already relies on POSIX features.  (The same probably applies to the
Windows API.)

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#91529

FromDavid Brown <david.brown@hesbynett.no>
Date2016-08-01 22:42 +0200
Message-ID<nnoc7k$h15$1@dont-email.me>
In reply to#91500
On 01/08/16 18:55, Keith Thompson wrote:
> David Brown <david.brown@hesbynett.no> writes:
> [...]
>> Personally, I would rather have have a selection of byte-sized types in
>> a language like C.  I would like a type "char" which can hold character
>> data such as 'a'.  But assigning an integer value to a char (without
>> appropriate casts) should be an error.  I would like a type "byte" which
>> represents raw data in memory - "byte *" would be used instead of "void
>> *" in C, and also in many cases where "char *" is used.  So functions
>> like "memcpy" would deal in "byte*" pointers, "malloc" would return a
>> "byte*", but "strcpy" would use "char*" pointers.  And I would like
>> numerical types of byte size.  To fit C practice, these might be "signed
>> short short int" and "unsigned short short int" (with "signed" being the
>> default), though I am sure some people would object to those names.
>
> Apart from the implicit conversion of numeric type to char, that's
> pretty much what we have.  `char` is the type for (narrow) characters,
> `unsigned char` represents raw data, and `signed char` is a narrow
> signed integer type.

It is not far off, though I'd prefer to drop the implicit conversions, 
and have somewhat different rules for promotion and aliasing.  And I 
would prefer standard names that matched such usage.

>
>> But we have what we have in C - it's not going to change.  The best we
>> can do is write code in a way that minimises the risk of errors - and
>> that includes being explicit about using signed or unsigned char when
>> using them for numbers.
>
> Agreed.
>
> As for uint8_t and int8_t, you should use those only if you need
> *exactly* 8 bits.  If you just want a narrow integer type of *at least*
> 8 bits, you can use unsigned char and signed char -- or
> [u]int_(least|fast)8_t, depending on your requirements.

Certainly that is suitable for some tasks, especially those that need 
maximal portability (since these types usually exist even when CHAR_BIT 
!= 8).  And often those types are more explicit descriptions of exactly 
what you are looking for.

In my experience (embedded programming), however, I often know exactly 
the size I want and thus the precisely sized types are best.  But the 
standard supports both choices, because needs and preferences vary.

And - IMHO - the least/fast types are ugly!

>
> [...]
>
>> One should, of course, rely on CHAR_BIT == 8 without ensuring a clear
>> compile-time failure if that is not the case.  That might be done by
>> testing CHAR_BIT and issuing a #error directive - but IMHO it is good
>> enough to simply make use of uint8_t and int8_t types.
>
> I presume you omitted a "not" there.

You presume correctly.  Thanks.

>
> On the other hand, it's reasonable to assume CHAR_BIT == 8 if your code
> already relies on POSIX features.  (The same probably applies to the
> Windows API.)
>

Yes - that's another perfectly good alternative.  It's fine to have 
assumptions that are appropriate for the sort of code you are writing, 
but it is good practice to make sure there are clear compile-time 
failures if the assumptions don't hold.  Calling POSIX functions or 
using POSIX headers is a good way to get a failure if someone uses the 
code in a non-POSIX system without due modifications.

[toc] | [prev] | [next] | [standalone]


#91532

Fromsupercat@casperkitty.com
Date2016-08-01 14:18 -0700
Message-ID<157999a4-830d-490f-b5d6-d1f64223137f@googlegroups.com>
In reply to#91529
On Monday, August 1, 2016 at 3:42:38 PM UTC-5, David Brown wrote:
> And - IMHO - the least/fast types are ugly!

Which types are faster or slower is often dependent upon whether variables
happen to be stored in registers.  On something like the ARM7-TDMI, given
"uint16_t x; uint32_t y;", the code "x++; y++;" will generate

    ; x++
    add r4,r4,#1
    mov r4,r4,lsl #16
    mov r4,r4,lsr #16
    ; y++
    add r5,r5,#1

if the variables are in registers [using uint32_t is 3x as fast] but if
the variables aren't in registers, the code would be:

    ; x++
    ldr  r0,=_x
    ldrh r1,[r0]
    add  r1,#1
    strh r1,[r0]
    ; y++
    ldr  r0,=_x
    ldr  r1,[r0]
    add  r1,#1
    str  r1,[r0]

No speed advantage for the 32-bit types, but some operations (e.g.
using memcpy on an array) will be faster when using smaller types
than when using larger ones.  So what size should a "fast" 16 bit
type be?

What would be genuinely helpful would be integer types whose semantics
were independent of the sizes of "int" or other such types.  On a 16-bit
system, multiplying any two uint16_t values will always yield a mod-65536
uint16_t value (the result is always defined).  On a 32-bit system, even
if the result of a multiply is coerced into a uint16_t, that is not enough
to ensure mod-65536 multiplication.

It would be helpful to have a wrap16_t type which was defined as behaving,
regardless of the size of "int", the way a uint16_t behaves on 16-bit
systems [operations with two values of type "wrap16_t" would simply use
that type, as would those with a "wrap16_t" and a simple integer constant
0 to 65535; any operations that would require a promotion to "int" or
"unsigned" would issue a diagnostic].  The C Standard would not presently
allow an implementation to have integer types that behaved in such fashion,
but they would make it much easier to write code that can port smoothly to
platforms with larger "int" sizes.

[toc] | [prev] | [next] | [standalone]


#91506

FromLes Cargill <lcargill99@comcast.com>
Date2016-08-01 13:11 -0500
Message-ID<nno33q$fto$1@dont-email.me>
In reply to#91490
David Brown wrote:
> On 01/08/16 16:59, Les Cargill wrote:
>> David Brown wrote:
>>> On 31/07/16 19:40, Osmium wrote:
>>>
>>>>
>>>> A novice would naturally think that char was signed by default, the same
>>>> as an int.  It is not, the default is chosen by the compiler writer.
>>>> Among other things, this has ramifications in bit shifting within
>>>> characters,.
>>>
>>> A novice may equally well think that a char was /unsigned/ by default,
>>> since the obvious interpretation of "char" is "character", such as
>>> letters, digits, etc. - and the concept of a "negative character" is
>>> totally meaningless.
>>>
>>
>>
>> So then they must learn that a char is a specialization of an int. And
>> ints default to signed because the integers are both negative and
>> positive in mathematics.
>
> But "char" is not a "specialisation of an int" in C - they have
> different properties, and neither is a subset of the other.  And while
> "int" is signed in C, "char" is not necessarily signed.
>

So I'm calling that a swing and a miss. A char is an int that is
constrained to be less bits. All chars have exactly the same semantics
as ints. Default char in 'C' is always unsigned unless you use compiler
options to make it otherwise, or unless the compiler defaults it for you.

> And the reason C's most common type, "int", is signed is because that is
> a practical and useful feature for a type in programming - not because
> integers are signed in mathematics.  C "int" and mathematical integers
> are different things.
>

Of course they are; but 'C' ints have aspects of mathematical
"integers".

>>
>>> Clearly, assuming that "char" is unsigned by default is just as bad as
>>> assuming it is signed by default.  In any situation where you use char
>>> types to store numbers or whenever the signedness of char matters, you
>>> should be explicit about it.
>>>
>>
>> The present state of 'C' is arguably the least bad alternative. Most
>> problems in computing involve people complaining about default behavior
>> of systems that must serve many user bases, each of which needs its own
>> default behavior.
>
> Personally, I would rather have have a selection of byte-sized types in
> a language like C.

But you do. Use <stdint.h>; it copies in nicely if it's not part of the 
header file firmament of your toolchain. If it doesn't, munge it as part 
of a project-local header suite.

  I would like a type "char" which can hold character
> data such as 'a'.  But assigning an integer value to a char (without
> appropriate casts) should be an error.

The problem is that there's a great and powerful simplifying assumption
in play - 'a' is exactly equivalent to the integer 0xa1. I find this
quite comforting; it's a simple rule.

> I would like a type "byte" which
> represents raw data in memory - "byte *" would be used instead of "void
> *" in C, and also in many cases where "char *" is used.

I rather like "void *" because void is the identity un-type - it is a
type with zero semantic information about it. A void * is a pointer for
the sake of a pointer, used only as an r-value in order to assign or
cast to a richer type.

> So functions
> like "memcpy" would deal in "byte*" pointers, "malloc" would return a
> "byte*", but "strcpy" would use "char*" pointers.  And I would like
> numerical types of byte size.  To fit C practice, these might be "signed
> short short int" and "unsigned short short int" (with "signed" being the
> default), though I am sure some people would object to those names.
>

Since we can already do anything we need to with the existing tools 
without the additional cruft, I fail to see any gain from it.

> But we have what we have in C - it's not going to change.  The best we
> can do is write code in a way that minimises the risk of errors - and
> that includes being explicit about using signed or unsigned char when
> using them for numbers.
>

"'C' doesn't change" is rather the point. There are other language 
systems which flaunt this.

>>
>>
>>> Since this is in the context of teaching C, I think programmers should
>>> be strongly encouraged not to consider "char" for arithmetic at all -
>>> including bit shifting (what does it mean to bit-shift a "z"
>>> character?).  They should be encouraged to use "uint8_t" and "int8_t" as
>>> appropriate.
>>>
>>
>> And this is all fine until you port to C++ and use -Wall on certain
>> toolchains. :)
>
> Why is that a problem?


Because warnings. With the right compiler options, C++ expects a char * 
to be a char *, not some typedef equivalent to a char *.

This happens with Mingw 3.4.5 with g++ -I . -Wall -c

> And more particularly, why would it be a problem
> if you use "uint8_t" and "int8_t" but not a problem when you use "char",
> "signed char" and "unsigned char"?
>
> (Again, this is assuming that uint8_t and int8_t exist on that target.)
>
>>
>>> I know there are targets that don't support uint8_t or int8_t.  But
>>> these are few and far between these days, and mostly for rather
>>> specialised programming.
>>
>> Most programming is highly specialized these days.
>
> Most programming is not for DSPs or dinosaur mainframes.  The
> programming domain may be specialised, but it will very rarely need to
> run on targets with CHAR_BIT != 8.

Indeed.

> So if the using of uint8_t and
> int8_t makes code clearer, simpler, more efficient, or easier to
> maintain, then I believe those types should be used freely in most cases.
>

I won't disagree, the cases where it causes problems all to the side.

> One should, of course, rely on CHAR_BIT == 8 without ensuring a clear
> compile-time failure if that is not the case.  That might be done by
> testing CHAR_BIT and issuing a #error directive - but IMHO it is good
> enough to simply make use of uint8_t and int8_t types.
>

#assert(CHAR_BIT==8) is easy enough.

>>
>>> People should be taught that such systems
>>> exist, but for most programming tasks you can freely use uint8_t and
>>> friends if that is what makes your code clearer and more sensible.
>>>
>>> And with bit shifts in particular, people should be taught to stick to
>>> unsigned types when doing bit manipulation.  It is almost always the
>>> type you want, and you run far less risk of accidentally getting
>>> undefined behaviour.
>>>
>>
>>
>

-- 
Les Cargill

[toc] | [prev] | [next] | [standalone]


#91511

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2016-08-01 19:46 +0100
Message-ID<87h9b4uy39.fsf@bsb.me.uk>
In reply to#91506
Les Cargill <lcargill99@comcast.com> writes:

> David Brown wrote:
>> On 01/08/16 16:59, Les Cargill wrote:
>>> David Brown wrote:
>>>> On 31/07/16 19:40, Osmium wrote:
>>>>
>>>>>
>>>>> A novice would naturally think that char was signed by default, the same
>>>>> as an int.  It is not, the default is chosen by the compiler writer.
>>>>> Among other things, this has ramifications in bit shifting within
>>>>> characters,.
>>>>
>>>> A novice may equally well think that a char was /unsigned/ by default,
>>>> since the obvious interpretation of "char" is "character", such as
>>>> letters, digits, etc. - and the concept of a "negative character" is
>>>> totally meaningless.
>>>
>>> So then they must learn that a char is a specialization of an int. And
>>> ints default to signed because the integers are both negative and
>>> positive in mathematics.
>>
>> But "char" is not a "specialisation of an int" in C - they have
>> different properties, and neither is a subset of the other.  And while
>> "int" is signed in C, "char" is not necessarily signed.
>
> So I'm calling that a swing and a miss. A char is an int that is
> constrained to be less bits. All chars have exactly the same semantics
> as ints. Default char in 'C' is always unsigned unless you use compiler
> options to make it otherwise, or unless the compiler defaults it for
> you.

Quite a lot of that is wrong.  A char is not an int with fewer bits.
For one thing, it might have the same number of bits, and, even when it
has fewer, it may be unsigned making it very unlike an int with fewer
bits.  That means that char does not always have the same semantics as
int.

The last bit reads oddly but ends up being right because it says that
char is always unsigned except when it isn't.

<snip>
> The problem is that there's a great and powerful simplifying assumption
> in play - 'a' is exactly equivalent to the integer 0xa1. I find this
> quite comforting; it's a simple rule.

In C, the character constant 'a' certainly has type int, but you can't
say what the value is.  0xa1 is a possible value but where did that come
from?  (If you'd said 0x61 (ASCII) or 0x81 (EBCDIC) I would not have been
too surprised.)

>> I would like a type "byte" which
>> represents raw data in memory - "byte *" would be used instead of "void
>> *" in C, and also in many cases where "char *" is used.
>
> I rather like "void *" because void is the identity un-type - it is a
> type with zero semantic information about it. A void * is a pointer for
> the sake of a pointer, used only as an r-value in order to assign or
> cast to a richer type.

I think I know what you are getting at (basically that you can't do much
with a void *) but in C you can have l-value expressions of void * type.

<snip>
-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#91546

FromLes Cargill <lcargill99@comcast.com>
Date2016-08-01 18:20 -0500
Message-ID<nnol7a$fk6$1@dont-email.me>
In reply to#91511
Ben Bacarisse wrote:
> Les Cargill <lcargill99@comcast.com> writes:
>
>> David Brown wrote:
>>> On 01/08/16 16:59, Les Cargill wrote:
>>>> David Brown wrote:
>>>>> On 31/07/16 19:40, Osmium wrote:
>>>>>
>>>>>>
>>>>>> A novice would naturally think that char was signed by default, the same
>>>>>> as an int.  It is not, the default is chosen by the compiler writer.
>>>>>> Among other things, this has ramifications in bit shifting within
>>>>>> characters,.
>>>>>
>>>>> A novice may equally well think that a char was /unsigned/ by default,
>>>>> since the obvious interpretation of "char" is "character", such as
>>>>> letters, digits, etc. - and the concept of a "negative character" is
>>>>> totally meaningless.
>>>>
>>>> So then they must learn that a char is a specialization of an int. And
>>>> ints default to signed because the integers are both negative and
>>>> positive in mathematics.
>>>
>>> But "char" is not a "specialisation of an int" in C - they have
>>> different properties, and neither is a subset of the other.  And while
>>> "int" is signed in C, "char" is not necessarily signed.
>>
>> So I'm calling that a swing and a miss. A char is an int that is
>> constrained to be less bits. All chars have exactly the same semantics
>> as ints. Default char in 'C' is always unsigned unless you use compiler
>> options to make it otherwise, or unless the compiler defaults it for
>> you.
>
> Quite a lot of that is wrong.  A char is not an int with fewer bits.
> For one thing, it might have the same number of bits, and, even when it
> has fewer,

It may well have the same number of bits, although this is rather 
unusual (I'm looking at you, TI :) .

The general case is that char is smaller. Look, this is mostly
straight out of K&R and remains true to this day.

> it may be unsigned making it very unlike an int with fewer
> bits.  That means that char does not always have the same semantics as
> int.
>
> The last bit reads oddly but ends up being right because it says that
> char is always unsigned except when it isn't.
>

While it's implementation dependent, it's unusual for "unsigned" to be 
the actual default - unless overridden.

char types inherit int semantics - again. Implementations people are 
most like to encounter certainly have this property.

> <snip>
>> The problem is that there's a great and powerful simplifying assumption
>> in play - 'a' is exactly equivalent to the integer 0xa1. I find this
>> quite comforting; it's a simple rule.
>
> In C, the character constant 'a' certainly has type int, but you can't
> say what the value is.  0xa1 is a possible value but where did that come
> from?  (If you'd said 0x61 (ASCII) or 0x81 (EBCDIC) I would not have been
> too surprised.)
>

I meant 0x61. :)

>>> I would like a type "byte" which
>>> represents raw data in memory - "byte *" would be used instead of "void
>>> *" in C, and also in many cases where "char *" is used.
>>
>> I rather like "void *" because void is the identity un-type - it is a
>> type with zero semantic information about it. A void * is a pointer for
>> the sake of a pointer, used only as an r-value in order to assign or
>> cast to a richer type.
>
> I think I know what you are getting at (basically that you can't do much
> with a void *) but in C you can have l-value expressions of void * type.
>

Yes, of course. I meant its only use *as* an r-value requires further 
qualification.

> <snip>
>

-- 
Les Cargill

[toc] | [prev] | [next] | [standalone]


#91559

FromDavid Brown <david.brown@hesbynett.no>
Date2016-08-02 10:18 +0200
Message-ID<nnpl0b$p7u$1@dont-email.me>
In reply to#91546
On 02/08/16 01:20, Les Cargill wrote:
> Ben Bacarisse wrote:
>> Les Cargill <lcargill99@comcast.com> writes:
>>
>>> David Brown wrote:
>>>> On 01/08/16 16:59, Les Cargill wrote:
>>>>> David Brown wrote:
>>>>>> On 31/07/16 19:40, Osmium wrote:
>>>>>>
>>>>>>>
>>>>>>> A novice would naturally think that char was signed by default,
>>>>>>> the same
>>>>>>> as an int.  It is not, the default is chosen by the compiler writer.
>>>>>>> Among other things, this has ramifications in bit shifting within
>>>>>>> characters,.
>>>>>>
>>>>>> A novice may equally well think that a char was /unsigned/ by
>>>>>> default,
>>>>>> since the obvious interpretation of "char" is "character", such as
>>>>>> letters, digits, etc. - and the concept of a "negative character" is
>>>>>> totally meaningless.
>>>>>
>>>>> So then they must learn that a char is a specialization of an int. And
>>>>> ints default to signed because the integers are both negative and
>>>>> positive in mathematics.
>>>>
>>>> But "char" is not a "specialisation of an int" in C - they have
>>>> different properties, and neither is a subset of the other.  And while
>>>> "int" is signed in C, "char" is not necessarily signed.
>>>
>>> So I'm calling that a swing and a miss. A char is an int that is
>>> constrained to be less bits. All chars have exactly the same semantics
>>> as ints. Default char in 'C' is always unsigned unless you use compiler
>>> options to make it otherwise, or unless the compiler defaults it for
>>> you.
>>
>> Quite a lot of that is wrong.  A char is not an int with fewer bits.
>> For one thing, it might have the same number of bits, and, even when it
>> has fewer,
> 
> It may well have the same number of bits, although this is rather
> unusual (I'm looking at you, TI :) .
> 
> The general case is that char is smaller. Look, this is mostly
> straight out of K&R and remains true to this day.
> 

True, in many cases - but not always.  To be a general rule, it needs to
be true in all cases (at least all real-world cases.  I don't worry too
much about the hypothetical ones).

And as well as cases where CHAR_BIT > 8, there are also some
non-conforming compilers for 8-bit microcontrollers that have 8-bit
int's.  These break some pretty fundamentals about C, but are often
useful tools for such chips and most of what you write is normal C code.

>> it may be unsigned making it very unlike an int with fewer
>> bits.  That means that char does not always have the same semantics as
>> int.
>>
>> The last bit reads oddly but ends up being right because it says that
>> char is always unsigned except when it isn't.
>>
> 
> While it's implementation dependent, it's unusual for "unsigned" to be
> the actual default - unless overridden.

I think that is a wild generalisation, without basis in fact - unless
you can point us to a list of compilers, targets, and the signedness of
their chars.  It may be common for hosted implementations to chars
signed by default, but it is common in embedded systems to make unsigned
the default.  I would not like to try to guess which is most common, but
I certainly would not accept your claim of a clear bias without
statistical evidence.  Any assumption about the signedness of plain
char, is simply a bad idea.

[toc] | [prev] | [next] | [standalone]


#91564

FromLes Cargill <lcargill99@comcast.com>
Date2016-08-02 09:35 -0500
Message-ID<nnqaph$ho$1@dont-email.me>
In reply to#91559
David Brown wrote:
> On 02/08/16 01:20, Les Cargill wrote:
>> Ben Bacarisse wrote:
>>> Les Cargill <lcargill99@comcast.com> writes:
>>>
>>>> David Brown wrote:
>>>>> On 01/08/16 16:59, Les Cargill wrote:
>>>>>> David Brown wrote:
>>>>>>> On 31/07/16 19:40, Osmium wrote:
>>>>>>>
>>>>>>>>
>>>>>>>> A novice would naturally think that char was signed by default,
>>>>>>>> the same
>>>>>>>> as an int.  It is not, the default is chosen by the compiler writer.
>>>>>>>> Among other things, this has ramifications in bit shifting within
>>>>>>>> characters,.
>>>>>>>
>>>>>>> A novice may equally well think that a char was /unsigned/ by
>>>>>>> default,
>>>>>>> since the obvious interpretation of "char" is "character", such as
>>>>>>> letters, digits, etc. - and the concept of a "negative character" is
>>>>>>> totally meaningless.
>>>>>>
>>>>>> So then they must learn that a char is a specialization of an int. And
>>>>>> ints default to signed because the integers are both negative and
>>>>>> positive in mathematics.
>>>>>
>>>>> But "char" is not a "specialisation of an int" in C - they have
>>>>> different properties, and neither is a subset of the other.  And while
>>>>> "int" is signed in C, "char" is not necessarily signed.
>>>>
>>>> So I'm calling that a swing and a miss. A char is an int that is
>>>> constrained to be less bits. All chars have exactly the same semantics
>>>> as ints. Default char in 'C' is always unsigned unless you use compiler
>>>> options to make it otherwise, or unless the compiler defaults it for
>>>> you.
>>>
>>> Quite a lot of that is wrong.  A char is not an int with fewer bits.
>>> For one thing, it might have the same number of bits, and, even when it
>>> has fewer,
>>
>> It may well have the same number of bits, although this is rather
>> unusual (I'm looking at you, TI :) .
>>
>> The general case is that char is smaller. Look, this is mostly
>> straight out of K&R and remains true to this day.
>>
>
> True, in many cases - but not always.  To be a general rule, it needs to
> be true in all cases (at least all real-world cases.  I don't worry too
> much about the hypothetical ones).
>
> And as well as cases where CHAR_BIT > 8, there are also some
> non-conforming compilers for 8-bit microcontrollers that have 8-bit
> int's.  These break some pretty fundamentals about C, but are often
> useful tools for such chips and most of what you write is normal C code.
>
>>> it may be unsigned making it very unlike an int with fewer
>>> bits.  That means that char does not always have the same semantics as
>>> int.
>>>
>>> The last bit reads oddly but ends up being right because it says that
>>> char is always unsigned except when it isn't.
>>>
>>
>> While it's implementation dependent, it's unusual for "unsigned" to be
>> the actual default - unless overridden.
>
> I think that is a wild generalisation, without basis in fact - unless
> you can point us to a list of compilers, targets, and the signedness of
> their chars.

Hence "unless overridden". The defacto, default standards for the 'C'
language are "char is a smaller int" and "ints are signed by default."

The Standard obviously doesn't say one way or the other. But the 
historical critical mass of the language is towards the way I say.

   It may be common for hosted implementations to chars
> signed by default, but it is common in embedded systems to make unsigned
> the default.  I would not like to try to guess which is most common, but
> I certainly would not accept your claim of a clear bias without
> statistical evidence.  Any assumption about the signedness of plain
> char, is simply a bad idea.
>
>

We're still talking about two different things. But that's okay.

Discussions in c.l.c tend towards oscillating between the universal and
the .. profanely local. But there really are base cases that tend to be
more likely to be encountered. These base cases have a historical
footing.

But as you say, when faced with a new implementation, you have to check.

Embedded systems tend to make char unsigned for various reasons - most
are pretty sound. But they're mainly so that debuggers and/or printf
represent 8 byte  chars in hexadecimal without integer sign extension.


-- 
Les Cargill

[toc] | [prev] | [next] | [standalone]


#91566

FromKeith Thompson <kst-u@mib.org>
Date2016-08-02 08:00 -0700
Message-ID<lnmvkv2p35.fsf@kst-u.example.com>
In reply to#91564
Les Cargill <lcargill99@comcast.com> writes:
> David Brown wrote:
>> On 02/08/16 01:20, Les Cargill wrote:
[...]
>>> While it's implementation dependent, it's unusual for "unsigned" to be
>>> the actual default - unless overridden.
>>
>> I think that is a wild generalisation, without basis in fact - unless
>> you can point us to a list of compilers, targets, and the signedness of
>> their chars.
>
> Hence "unless overridden". The defacto, default standards for the 'C'
> language are "char is a smaller int" and "ints are signed by default."

char is not "a smaller int".  char and int are both integer types.
And yes, char is almost always smaller than int.

Yes, int is signed by default.  In fact, int is signed; it's not
just a default, it's a firm language rule.  Is that what you meant?

I think you meant to say, or imply, that plain char is signed by
default.  That statement is neither true nor useful.  And upthread,
you wrote the opposite (which is also misleading):

    Default char in 'C' is always unsigned unless you use compiler
    options to make it otherwise, or unless the compiler defaults it for
    you.

There is no default signedness for type char.  It is either signed or
unsigned, depending on the implementation.  It's probably true that
most modern hosted impleentations make plain char signed, but that
does not constitute a "default".  Code that's intended to be even
minimally portable must not depend on the signedness of plain char.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#91569

FromLes Cargill <lcargill99@comcast.com>
Date2016-08-02 11:12 -0500
Message-ID<nnqgep$kes$1@dont-email.me>
In reply to#91566
Keith Thompson wrote:
> Les Cargill <lcargill99@comcast.com> writes:
>> David Brown wrote:
>>> On 02/08/16 01:20, Les Cargill wrote:
> [...]
>>>> While it's implementation dependent, it's unusual for "unsigned" to be
>>>> the actual default - unless overridden.
>>>
>>> I think that is a wild generalisation, without basis in fact - unless
>>> you can point us to a list of compilers, targets, and the signedness of
>>> their chars.
>>
>> Hence "unless overridden". The defacto, default standards for the 'C'
>> language are "char is a smaller int" and "ints are signed by default."
>
> char is not "a smaller int".  char and int are both integer types.
> And yes, char is almost always smaller than int.
>
> Yes, int is signed by default.  In fact, int is signed; it's not
> just a default, it's a firm language rule.  Is that what you meant?
>
> I think you meant to say, or imply, that plain char is signed by
> default.  That statement is neither true nor useful.  And upthread,
> you wrote the opposite (which is also misleading):
>
>      Default char in 'C' is always unsigned unless you use compiler
>      options to make it otherwise, or unless the compiler defaults it for
>      you.
>

I meant signed. Sorry about that.

> There is no default signedness for type char.  It is either signed or
> unsigned, depending on the implementation.  It's probably true that
> most modern hosted impleentations make plain char signed, but that
> does not constitute a "default".

I'd disagree, because of the transitive property of assumptions.

> Code that's intended to be even
> minimally portable must not depend on the signedness of plain char.
>

That's a whole 'nother mess.

-- 
Les Cargill

[toc] | [prev] | [next] | [standalone]


#91567

FromDavid Brown <david.brown@hesbynett.no>
Date2016-08-02 17:11 +0200
Message-ID<nnqd6i$92c$1@dont-email.me>
In reply to#91564
On 02/08/16 16:35, Les Cargill wrote:
> David Brown wrote:
>> On 02/08/16 01:20, Les Cargill wrote:
>>> Ben Bacarisse wrote:
>>>> Les Cargill <lcargill99@comcast.com> writes:
<snip>
>>> While it's implementation dependent, it's unusual for "unsigned" to be
>>> the actual default - unless overridden.
>>
>> I think that is a wild generalisation, without basis in fact - unless
>> you can point us to a list of compilers, targets, and the signedness of
>> their chars.
> 
> Hence "unless overridden". The defacto, default standards for the 'C'
> language are "char is a smaller int" and "ints are signed by default."
> 
> The Standard obviously doesn't say one way or the other. But the
> historical critical mass of the language is towards the way I say.

There is /no/ standard here - defacto, default, or otherwise.  Unless
you can point to a list of C implementations for a range of processors,
from small 8-bit to large 64-bit, showing a clear bias for a "defacto
standard" of plain char being signed, then you are just spreading a
myth.  I expect the list to cover some 40+ common architectures, and
have at least 80% "signed".  I also expect that for each target cpu,
/all/ major compilers agree on the signedness of plain char.

Just to get you started, x86 is usually signed as is AVR, while ARM and
PPC are usually unsigned.  I have also seen unsigned on the AVR.


Given a reference such as that, I will happily accept your "defacto
default standard" (though it will not affect the recommendation to
always be explicit when the signedness matters).  Failing such a
reference, I think the the "default" is in your mind alone.

(We all have our assumptions that we have lived with for years, until
someone points them out.  The question is, can you justify your beliefs
here - or can you accept that they are not as valid as you once thought?)

> 
>   It may be common for hosted implementations to chars
>> signed by default, but it is common in embedded systems to make unsigned
>> the default.  I would not like to try to guess which is most common, but
>> I certainly would not accept your claim of a clear bias without
>> statistical evidence.  Any assumption about the signedness of plain
>> char, is simply a bad idea.
>>
>>
> 
> We're still talking about two different things. But that's okay.

No, it's just one point here.  You are claiming that plain char is
signed by "defacto default" in all but "unusual" implementations.  I am
asking you to justify that, or accept that there is /no/ standard here.

(Some compilers allow you to change the signedness through a command
line switch.)

> 
> Discussions in c.l.c tend towards oscillating between the universal and
> the .. profanely local. But there really are base cases that tend to be
> more likely to be encountered. These base cases have a historical
> footing.
> 
> But as you say, when faced with a new implementation, you have to check.
> 
> Embedded systems tend to make char unsigned for various reasons - most
> are pretty sound. But they're mainly so that debuggers and/or printf
> represent 8 byte  chars in hexadecimal without integer sign extension.
> 

No, embedded systems usually make plain char unsigned because unsigned
chars are more useful in most systems (in cases where the signedness
matters or makes sense).  Embedded systems don't usually have the same
historical baggage that made signed char the default on many big systems.

Think about what "char" types are used for.  Think how often you want to
store negative numbers in them.  Think how often you want to treat them
as a raw set of 8 (usually) bits without any concept of signs or
negative values.  Think about how often you want to store characters
that have negative code values - and how often you want to store
characters that might be in the range 128 - 255.

The folks that design ABI's for chips, or pick configurations for
compilers, /do/ think about that sort of thing.  That's why they will
often pick unsigned for the default, unless there are historical or
compatibility reasons for picking signed.  But as I don't have any sort
of list or reference, I can't claim that they /usually/ pick unsigned
for plain char - only that it usually makes more sense.


[toc] | [prev] | [next] | [standalone]


#91570

FromLes Cargill <lcargill99@comcast.com>
Date2016-08-02 11:55 -0500
Message-ID<nnqj06$u15$1@dont-email.me>
In reply to#91567
David Brown wrote:
> On 02/08/16 16:35, Les Cargill wrote:
>> David Brown wrote:
>>> On 02/08/16 01:20, Les Cargill wrote:
>>>> Ben Bacarisse wrote:
>>>>> Les Cargill <lcargill99@comcast.com> writes:
> <snip>
>>>> While it's implementation dependent, it's unusual for "unsigned" to be
>>>> the actual default - unless overridden.
>>>
>>> I think that is a wild generalisation, without basis in fact - unless
>>> you can point us to a list of compilers, targets, and the signedness of
>>> their chars.
>>
>> Hence "unless overridden". The defacto, default standards for the 'C'
>> language are "char is a smaller int" and "ints are signed by default."
>>
>> The Standard obviously doesn't say one way or the other. But the
>> historical critical mass of the language is towards the way I say.
>
> There is /no/ standard here - defacto, default, or otherwise.

I simply have to disagree. The default 'C' int declaration is signed
unless it's explicitly made unsigned.

That people choose to override that default is neither here nor there.
It's baked into the declaration syntax of the language.

<snip>
-- 
Les Cargill

[toc] | [prev] | [next] | [standalone]


#91572

Fromsupercat@casperkitty.com
Date2016-08-02 10:16 -0700
Message-ID<0584a001-91b8-48d9-80de-3c7db52f5aaa@googlegroups.com>
In reply to#91570
On Tuesday, August 2, 2016 at 11:50:36 AM UTC-5, Les Cargill wrote:
> I simply have to disagree. The default 'C' int declaration is signed
> unless it's explicitly made unsigned.

All ASCII characters are in the range 0..127, so all members of the C Character Set are guaranteed have character codes in the range 0..SCHAR_MAX regardless of CHAR_BITS.

Implementations which use non-ASCII character sets may have characters whose codes are greater than SCHAR_MAX.  That would imply that unqualified `char` must be unsigned on such platforms, since all members of the C character set are required to have non-negative character codes.

On the flip side, a lot of code relies upon having all values of type `char` be representable as type `int`; implementations where `unsigned char` has a larger range than `signed int` would violate that expectation of unqualified `char` were unsigned.

[toc] | [prev] | [next] | [standalone]


#91595

FromDavid Brown <david.brown@hesbynett.no>
Date2016-08-03 14:02 +0200
Message-ID<nnsmgd$gcm$1@dont-email.me>
In reply to#91572
On 02/08/16 19:16, supercat@casperkitty.com wrote:
> On Tuesday, August 2, 2016 at 11:50:36 AM UTC-5, Les Cargill wrote:
>> I simply have to disagree. The default 'C' int declaration is
>> signed unless it's explicitly made unsigned.
> 
> All ASCII characters are in the range 0..127, so all members of the C
> Character Set are guaranteed have character codes in the range
> 0..SCHAR_MAX regardless of CHAR_BITS.

True - for a C implementation that uses ASCII.  But the standards don't
require ASCII, and C can be implemented with many different character
sets as long as they cover the standard 26 letter Latin alphabet, 10
digits, and a range of punctuation and symbols.  Historically, EBCDIC
has probably been popular on some systems.  And in modern tools, UTF-8
and Latin-1 (Windows CP1252, IIRC) are also common for the execution
character set (if not necessarily for the source character set).  Those
use characters or encodings in the range 128-255 as well.

> 
> Implementations which use non-ASCII character sets may have
> characters whose codes are greater than SCHAR_MAX.  That would imply
> that unqualified `char` must be unsigned on such platforms, since all
> members of the C character set are required to have non-negative
> character codes.

No, a "char" only needs to be able to store any element of the "basic
execution character set".  This can be a subset of the full execution
character set.  In real implementations using UTF-8, Latin-1, or another
encoding (possibly multi-byte) for the execution character set would
have ASCII as the "basic execution character set".

> 
> On the flip side, a lot of code relies upon having all values of type
> `char` be representable as type `int`; implementations where
> `unsigned char` has a larger range than `signed int` would violate
> that expectation of unqualified `char` were unsigned.
> 

It is perfectly possible for a plain char to be an unsigned 16-bit value
while an int is a signed 16-bit value - thus there are valid "char"
values that cannot be represented as "int".  On systems with 16-bit CHAR
(such as some DSP's), it would not surprise me if this were the case.

[toc] | [prev] | [next] | [standalone]


#91609

FromKeith Thompson <kst-u@mib.org>
Date2016-08-03 08:58 -0700
Message-ID<ln60rh3kuk.fsf@kst-u.example.com>
In reply to#91595
David Brown <david.brown@hesbynett.no> writes:
> On 02/08/16 19:16, supercat@casperkitty.com wrote:
>> On Tuesday, August 2, 2016 at 11:50:36 AM UTC-5, Les Cargill wrote:
>>> I simply have to disagree. The default 'C' int declaration is
>>> signed unless it's explicitly made unsigned.
>> 
>> All ASCII characters are in the range 0..127, so all members of the C
>> Character Set are guaranteed have character codes in the range
>> 0..SCHAR_MAX regardless of CHAR_BITS.
>

it's not clear what you mean by "the C Character Set".  N1570 5.2.1
describes 4 different character sets: the (source and execution)
(basic and extended) character sets, all of which may differ.

> require ASCII, and C can be implemented with many different character
> sets as long as they cover the standard 26 letter Latin alphabet, 10
> digits, and a range of punctuation and symbols.  Historically, EBCDIC
> has probably been popular on some systems.  And in modern tools, UTF-8
> and Latin-1 (Windows CP1252, IIRC) are also common for the execution
> character set (if not necessarily for the source character set).  Those
> use characters or encodings in the range 128-255 as well.

All members of the basic execution character set (whose values
are listed in 5.2.1) are required to have nonnegative values
(N1570 6.2.5p3).  The value of SCHAR_MAX is irrelevant; all such
character must have values in the range 0..CHAR_MAX.

For systems that use ASCII, this can be achieved by using
CHAR_BIT==8 and making plain char either signed or unsigned.  For
EBCDIC-based systems, if CHAR_BIT==8 plain char must be unsigned.
(An EBCDIC-based system with signed plain char and CHAR_BIT >= 9
is possible, but I seriously doubt that any such system exists.)

[...]

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


Page 1 of 2  [1] 2  Next page →

Back to top | Article view | comp.lang.c


csiph-web