Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #91409 > unrolled thread
| Started by | Keith Thompson <kst-u@mib.org> |
|---|---|
| First post | 2016-07-31 11:58 -0700 |
| Last post | 2016-07-31 17:06 -0500 |
| Articles | 4 — 4 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.
Re: unsigned int Keith Thompson <kst-u@mib.org> - 2016-07-31 11:58 -0700
Re: unsigned int supercat@casperkitty.com - 2016-07-31 12:28 -0700
Re: unsigned int Ian Collins <ian-news@hotmail.com> - 2016-08-01 07:33 +1200
Re: unsigned int Les Cargill <lcargill99@comcast.com> - 2016-07-31 17:06 -0500
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2016-07-31 11:58 -0700 |
| Subject | Re: unsigned int |
| Message-ID | <lnmvkx63ek.fsf@kst-u.example.com> |
ram@zedat.fu-berlin.de (Stefan Ram) writes:
> 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?)
The comparisons themselves don't give unexpected results; `<` yields a
true result if and only if its left operand is numerically less than its
right operand. But other operations can yield unexpected results, which
can in turn cause `<` to yield *seemingly* unexpected results.
An obvious example:
unsigned int x = 1;
if (-x < 0) ...
The value of the LHS of the `<` is UINT_MAX, not -1.
The promotion rules can also cause unexpected results for unsigned
types narrower than unsigned int.
> - there are suffixes for numerals to mark them as usigned,
> like »u«
"u" (or "U") is the *only* suffix that marks a constant as unsigned.
(I suggest using the standard term "constants" rather than
"numerals". "Literals" is also ok; the standard doesn't refer to
integer constants as literals, but the meaning is clear enough.)
> - 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++?)
In C90, an unsuffixed decimal integer constant is of type int, long
int, or unsigned long int, the first in which it can be represented.
In C99, this changed to int, long int, and long long int; an
unsuffixed decimal integer constant is never of an unsigned type.
This is unchanged in C11.
(In C++2003, the corresponding list is int, long int; C++2012
changed this to int, long int, long long int.)
> - A special conversion specification has to be used for
> printf (scanf will only be treated later in the course)
I'm not sure I'd call it any more "special" than the specification
for signed int. You need to use "%d" for signed int, "%u" for
unsigned int.
> - 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«.)
For all integer types, the behavior of arithmetic operations
follows the usual mathematical rules when all operands and results
are within the range of the type. For operands or results close
to the limits of the type, you get results that don't match the
corresponding results for mathematical integers -- undefined
behavior for signed types, defined wraparound for unsigned types.
(You can loosely think of the limits as singularities.)
For most signed integer types, for many problems, the limits have
very large magnitudes, and you likely don't have to worry about
running into them. For unsigned integer types, one of the limits
is at 0, which is easy to run into accidentally.
Gareth Owen's code:
for(x = strlen(s);x >= 0; --x) ...
is a good example of this.
--
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] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2016-07-31 12:28 -0700 |
| Message-ID | <c6056514-d93d-4aa7-8464-74a357872a13@googlegroups.com> |
| In reply to | #91409 |
On Sunday, July 31, 2016 at 1:58:20 PM UTC-5, Keith Thompson wrote:
> In C90, an unsuffixed decimal integer constant is of type int, long
> int, or unsigned long int, the first in which it can be represented.
>
> In C99, this changed to int, long int, and long long int; an
> unsuffixed decimal integer constant is never of an unsigned type.
> This is unchanged in C11.
Over the years, I've come to see the wisdom of Java's approach of requiring
that long constants be suffixed; if one has a piece of C code like:
#define SCALE_FACTOR 2500000000
int64_t scale_value(int32_t x) { return SCALE_FACTOR*2500000000; }
and the scale factor needs to be reduced by 20%, it's hardly obvious
that changing it to 2000000000 would break the code unless a suffix is
added. If the original had to be written as 2500000000LL, changing the
numeric value would not affect the type of the value.
If C99 had ruled that all integer literals beyond LNG_MAX need to be
suffixed, that would have avoided silent breakage of C89 code that
expects such types to be processed as "unsigned long".
[BTW, whether or not the Standard uses the term, I would favor "integer
literal" versus "integer constant", since the latter might also be used
informally to refer to integer constant expressions, or perhaps to some
things which the language may not regard as integer constant expressions
but may end up being processed as constants within the generated code
(e.g. the result of `offsetof`).
[toc] | [prev] | [next] | [standalone]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2016-08-01 07:33 +1200 |
| Message-ID | <e0723vFm9nU1@mid.individual.net> |
| In reply to | #91414 |
On 08/ 1/16 07:28 AM, supercat@casperkitty.com wrote:
> On Sunday, July 31, 2016 at 1:58:20 PM UTC-5, Keith Thompson wrote:
>> In C90, an unsuffixed decimal integer constant is of type int, long
>> int, or unsigned long int, the first in which it can be represented.
>>
>> In C99, this changed to int, long int, and long long int; an
>> unsuffixed decimal integer constant is never of an unsigned type.
>> This is unchanged in C11.
>
> Over the years, I've come to see the wisdom of Java's approach of requiring
> that long constants be suffixed; if one has a piece of C code like:
>
> #define SCALE_FACTOR 2500000000
>
> int64_t scale_value(int32_t x) { return SCALE_FACTOR*2500000000; }
>
> and the scale factor needs to be reduced by 20%, it's hardly obvious
> that changing it to 2000000000 would break the code unless a suffix is
> added. If the original had to be written as 2500000000LL, changing the
> numeric value would not affect the type of the value.
Or better still C had proper const so all of these ghastly macro
constants could be banished for ever...
--
Ian
[toc] | [prev] | [next] | [standalone]
| From | Les Cargill <lcargill99@comcast.com> |
|---|---|
| Date | 2016-07-31 17:06 -0500 |
| Message-ID | <nnlsgf$2ua$2@dont-email.me> |
| In reply to | #91415 |
Ian Collins wrote:
> On 08/ 1/16 07:28 AM, supercat@casperkitty.com wrote:
>> On Sunday, July 31, 2016 at 1:58:20 PM UTC-5, Keith Thompson wrote:
>>> In C90, an unsuffixed decimal integer constant is of type int, long
>>> int, or unsigned long int, the first in which it can be represented.
>>>
>>> In C99, this changed to int, long int, and long long int; an
>>> unsuffixed decimal integer constant is never of an unsigned type.
>>> This is unchanged in C11.
>>
>> Over the years, I've come to see the wisdom of Java's approach of
>> requiring
>> that long constants be suffixed; if one has a piece of C code like:
>>
>> #define SCALE_FACTOR 2500000000
>>
>> int64_t scale_value(int32_t x) { return SCALE_FACTOR*2500000000; }
>>
>> and the scale factor needs to be reduced by 20%, it's hardly obvious
>> that changing it to 2000000000 would break the code unless a suffix is
>> added. If the original had to be written as 2500000000LL, changing the
>> numeric value would not affect the type of the value.
>
> Or better still C had proper const so all of these ghastly macro
> constants could be banished for ever...
>
Use an enum in a header file. This being said, I find use of the
preprocessor much less than "ghastly".
--
Les Cargill
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.c
csiph-web