Question About Sequence Points and Interrupt/Thread Safety

I have my doubts that this works. -(1u) produces an int, value UINT_MAX. Assigning that to uc reduces that modulo (UCHAR_MAX +

1). I am not bothering to work out whether this is the same value (because I wouldn't use it), but I suspect it is influenced by such things as 1's complement or sign-mag representation, besides the different values of the various U*_MAX.
--
 [mail]: Chuck F (cbfalconer at maineline dot net) 
 [page]: 
            Try the download section.
Reply to
CBFalconer
Loading thread data ...

Nit-pick: I don't think so. It produces (on most implementation) an unsigned int. The type will be int only where int can represent all the values of unsigned int (possible but rare). On such a system the value is then -1. So it is never an int with value UINT_MAX. It is either an int with value -1 or a unsigned int with value UINT_MAX.

I can't see how the representation of negative numbers can affect the result. UCHAR_MAX + 1 is of the form 2^k for some k >= 8 [1]. UINT_MAX is of the form 2^n - 1 for n >= k. I.e. it is 2^(n-k) * 2^k

- 1 with n-k >= 0. This is congruent to 2^k - 1 mod 2^k, i.e. the result is UCHAR_MAX.

(Of course, if the expression is of type int with value -1 you also get UCHAR_MAX.)

[1] Please don't tell me I've used XOR -- I am trying to write mathematics in a restricted character set.
--
Ben.
Reply to
Ben Bacarisse

Yes, I knew that was what you were saying but it does not answer my question. What do some/all/most C compiler do about this? They have lots of options but the least appealing (to me) would be to abandon conformance.

I was commenting on your original suggestion where the type was tied to 0xff with no textual link. Where I need type-neutral code in C I would do it that way (though templates in that other language do it better).

Then don't comment it! I thought your point was that the assignment of -1 did not properly express what was happening.

It was not clear from your example that maxUInt would be used with only one type. (Yes, there was only one type, but the name is very general and it is not linked to the name of the type unlike your later example.) That is why I said one might have to check. If every type has it's own defined max that works fine for me, though I think it is overkill for unsigned types (that will always be unsigned).

--
Ben.
Reply to
Ben Bacarisse

I think I saw a retraction of that elsethread.

Can you C&V that please? Precisely which promotion and/or conversion do you think is taking place? I see an integer constant with type unsigned int and a unary minus operator acting on it to produce an unsigned int.

While that's not impossible, it's highly unlikely. (I think I used a DSP with effectively no unsigned types once, all unsigned stuff was just done within the positive values of signed int.)

As above, at what point do you believe signed types, and their representation, become involved in any way, and why?

Phil

--
I tried the Vista speech recognition by running the tutorial. I was 
amazed, it was awesome, recognised every word I said. Then I said the 
wrong word ... and it typed the right one. It was actually just 
detecting a sound and printing the expected word! -- pbhj on /.
Reply to
Phil Carmody

I don't know about some/all/most DSP C compilers, as I've only had the dubious pleasure of using a couple of them (one was okay, the other was a pain). Very often on DSPs, you get normal wrapping twos-compliment behaviour for standard integer operations, and only see saturating behaviour on DSP-specific functions (such as MAC operations). The saturation modes are typically controllable by flags or by using specific instruction variants.

I just mentioned them because sometimes on DSPs you have to deal with awkwardnesses that you don't get in other microcontroller programming. Other big pains you can encounter are minimal addressable sizes bigger than 8-bit (so "char" might be 16-bit), memory blocks that are 24-bits wide, multiple separate memory blocks that have different pointer types, etc. Trying to write code that is portable between such processors and "normal" processors is not an easy job!

There was no textual link in my earlier suggestion because the type I used was fixed - uint8_t. That is guaranteed to be 8-bit (compilers which can't implement an 8-bit value should not have an uint8_t defined, thus giving a compile-time error).

I agree that templates in the language-which-shall-not-be-named can be a more elegant way to handle such variable-type code (that's kind of what templates are for...)

-1 does not properly express what is happening. But "x = maxUInt" expresses it at least as clearly as "x = -1" with a comment - it is generally better to use the language rather than a comment.

I had in fact #define'd maxUInt to be -1, so that it *would* work with any unsigned type (it would still irritate lint, but the application source code is clear to the reader and writer, and that is the most important factor). If I had intended to use a width-specific max value, I'd have called it maxUInt8, or perhaps just used the definition UINT8_MAX.

mvh.,

David

Reply to
David Brown

Thanks for that clarification (my Ada knowledge is basically "I read a book once").

There is a difference here, however. For your type Unsigned_T, you are explicitly defining a modular type - thus -1 makes sense. When using type that is for unsigned integers, -1 does not make sense (and Ada rejects it).

Reply to
David Brown

Nate Eldredge wrote in news: snipped-for-privacy@vulcan.lan:

I stand corrected. Sorry all and thanks for the education.

GH

Reply to
Gil Hamilton

If I remember correctly, in ones-complement, -1 would be 11111110 in eight bits. Not UCHAR_MAX. Signed-magnitude is even stranger, 10000001 I think. Generalities are hard to deal with, generally. I have always lived in the twos-complement world where things work right. :-)

--
Joe Wright
"Memory is the second thing to go. I forget what the first is."
Reply to
Joe Wright

...

Yes, but as has been repeatedly ben pointed out, the representation is irrelevant; the standard defines the result of the conversion in terms of the value, not the representation.

Reply to
jameskuyper

Whether it works for unsigned char or not, it can definitely fail for unsigned types wider than unsigned int:

#include #include int main(void) { unsigned long long x = -1; unsigned long long y = -1u; printf("UINT_MAX = 0x%x\n", UINT_MAX); printf("ULLONG_MAX = 0x%llx\n", ULLONG_MAX); printf("x = 0x%llx\n", x); printf("y = 0x%llx\n", y); return 0; }

UINT_MAX = 0xffffffff ULLONG_MAX = 0xffffffffffffffff x = 0xffffffffffffffff y = 0xffffffff

The correct initialization of x depends on the conversion from a signed type to an unsigned type. In the initialization of y, since the initializer is already unsigned, its value is not affected by the type of y; the initializer has type unsigned int and value UINT_MAX, which can be converted to unsigned long long with no wraparound.

--
Keith Thompson (The_Other_Keith) kst@mib.org  
Nokia
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
Reply to
Keith Thompson

[snip]

Ah, but by using a C unsigned type, you *are* explicitly using a modular type.

--
Keith Thompson (The_Other_Keith) kst@mib.org  
Nokia
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
Reply to
Keith Thompson

Doesn't matter. The value is reduced modulo 2^CHAR_BIT on conversion to unsigned char, regardless of the representation used for negative signed chars: 6.3.1.3p2.

-- [mdw]

Reply to
Mark Wooding

So the problem is that the inventors of c didn't called them "modular integers". (Because the only difference is the name.)

Groetjes Albert

--

--
Albert van der Horst, UTRECHT,THE NETHERLANDS
Economic growth -- like all pyramid schemes -- ultimately falters.
albert@spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst
Reply to
Albert van der Horst

... snip ...

So why not use char, with whatever signage you want. You can check

8 bittedness in just one place with:

#if (8 != CHAR_BIT) error("need 8 bit system"); #endif

--
 [mail]: Chuck F (cbfalconer at maineline dot net) 
 [page]: 
            Try the download section.
Reply to
CBFalconer

... snip ...

No, which is why I used 'doubt'. It would require following the parsing of the expression, and ensuring that the compiler designer did likewise. That is why I would simply avoid it.

--
 [mail]: Chuck F (cbfalconer at maineline dot net) 
 [page]: 
            Try the download section.
Reply to
CBFalconer

... snip ...

So what? The value used is controlled by the overflow characteristics of unsigned, not by the representation. Read the standard.

Some useful references about C: (C-faq) (C99) (pre-C99) (C-library} (GNU docs)

--
 [mail]: Chuck F (cbfalconer at maineline dot net) 
 [page]: 
            Try the download section.
Reply to
CBFalconer

On 2009-03-03, CBFalconer wrote another Chucky special:

And of course error is, for instance, a function prototyped as

void error(int);

so that your compile time test actually results in some kind of compile-time error.

Reply to
Kaz Kylheku

The odds that a compiler designer would get the parsing of -(1u) wrong are somewhere between slim and none -- closer to the latter.

--
Keith Thompson (The_Other_Keith) kst@mib.org  
Nokia
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
Reply to
Keith Thompson

Presumably you mean:

#error "need 8 bit system"

And the parentheses on the condition are unnecessary. I'd write this as:

#if CHAR_BIT != 8 #error "CHAR_BIT != 8" #endif

Incidentally, this will trigger the #error if the "#include " is missing; the identifier CHAR_BIT will be replaced by 0. You could add an #ifdef to check for this -- but if you remember the #ifdef, you'll probably remember the #include.

This can get interesting if you're testing a macro whose expansion is expected to be 0. The best example I can think of from the standard library is:

#if EXIT_SUCCESS != 0 #error "EXIT_SUCCESS != 0" #endif

The error message will not be triggered either if EXIT_SUCCESS is defined as 0, or if you've forgotten the "#include ". One solution is:

#if ! defined EXIT_SUCCESS || EXIT_SUCCESS != 0 #error "EXIT_SUCCESS is undefined or non-zero" #endif

--
Keith Thompson (The_Other_Keith) kst@mib.org  
Nokia
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
Reply to
Keith Thompson

One of the main reasons for having a C standard is so that you *don't* have to check all these things for each compiler.

-- Richard

--
Please remember to mention me / in tapes you leave behind.
Reply to
Richard Tobin

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.