EmbeddedRelated.com
Forums

C and MISRA, blues... (arithmetic shifts)

Started by Nils April 24, 2008
Stefan Reuther wrote:

> '(-1) >> 1' is implementation-defined, not undefined.
Sorry. I mixed that up with the similar case (-1)<<1, which does cause undefined behaviour.
> Implementations that define it as 'exec("/usr/games/nethack")' are > rare.
They would be forbidden, actually. Running nethack would be undefined behaviour. But notice that it doesn't say anywhere what the implementation is or is not allowed to document as its implementation-specified result. It could perform arithmetic shifts on Mondays or in May, logical shifts otherwise.
CBFalconer wrote:
> Nils wrote: > ... snip ... >> int ArithmeticShiftRight (int value, unsigned int shift) { >> if (shift) { >> /* Get unsigned version of value to work with */ >> unsigned int x = (unsigned int) value; > > This operation is not possible in a standard C system.
Oh, but it is. Casting from signed to unsigned operates modulo (UINT_MAX+1) (C99 6.3.1.3p2). It's the other way round that isn't well-defined. The result of casting an unsigned number above INT_MAX to integer is implementation-defined. > Think about
> what would happen to negative values in sign-magnitude, 1's > complement, or 2's complement.
The same thing. The conversion is independent on representation.
CBFalconer wrote:
> Steve at fivetrees wrote: > ... snip ... >> Avoiding "goto" means avoiding unstructured design (i.e. using >> only only closed structures - one start, one end, any other >> context signalled by other means than programme flow). >> >> Exiting a control loop prematurely is not a case of a goto - >> it's still a case of one start, one end. It just avoids a layer >> of indenting and promotes readability. >> >> Things like jump tables are not lists of gotos - they're a list >> of (derefenced, if you insist) function pointers. >> >> Summary: avoiding goto as a design concept is a Good Thing. >> Avoiding gotos as a means of implementing good structure is >> simply misunderstanding the point. I've seen (possibly on this >> ng) someone defending goto on the basis that CPUs only know >> about branches and jumps anyway. Follocks. > > Not according to me. Consider the following function outline: > > int foo( /* whatever */ ) { > int errmk = 0; > FILE *f1, *f2, *fw; > > if (!(f1 = fopen(f1name, "r")) { > errmk = 1; goto f1bad; > } > else if (!(f2 = fopen(f2name, "r")) { > errmk = 2; goto f2bad; > } > else if (!(fw = fopen(fwname, "w")) { > errmk = 3; goto fwbad; > } > else { > /* files open, play appropriate games */ > } > fputs(fwendln, fw); > fclose(fw); > fwbad: > fclose(f2); > f2bad: > fclose(f1); > f1bad: > return errmk; > } > > There are lots of undetected errors left, that is an outline. Yes, > there are other ways to handle it. >
int foo( /* whatever */ ) { int errmk = 0; FILE *f1, *f2, *fw; if (!(f1 = fopen(f1name, "r")) { errmk = 1; } else { if (!(f2 = fopen(f2name, "r")) { errmk = 2; } else { if (!(fw = fopen(fwname, "w")) { errmk = 3; } else { /* Files open */ fputs(fwendln, fw); fclose(fw); }; fclose(f2); }; fclose(f1); }; return errmk; } Unless you are using a 40-character wide screen, that version is at least as good as your "goto" version. I've seen people claim that they "need" goto's to write good code - I've never actually had the need of one in anything I've written. I've done other "bad" things, such as "return" in the middle of loops, but I think "goto" is a bit more unstructured than that. Once you start doing things like jumping in and out of variable scopes with goto, you are asking for trouble (inefficient code, or even incorrect code). I don't mean to say that all goto's are wrong - just that you'd better have a much better excuse than that function before using it.

Stefan Reuther wrote:

> Walter Banks wrote: > > Steve at fivetrees wrote: > >>"Stefan Reuther" <stefan.news@arcor.de> wrote in message > >>> #if ((-1) >> 1) == -1 > >>> return value >> shift; > >>> #else > >>> # error Port me! > >>> #endif > >>> } > >>>which would make your code portable under all practical definitions > >>>known to me. > >> > >>I totally agree - I do exactly this as a matter of routine. I strongly > >>encourage the use of macro-level platform traps which say "if this isn't > >>the platform I made allowances for and assumptions about, then yell - > >>don't just compile incorrectly". > > > > I agree with the idea but be careful of the implementation. > > The math executed in > > #if ((-1) >> 1) == -1 > > is done so with the preprocessor and not the runtime > > environment. They may not be the same. > > If I read ISO 9899:1999 correctly, they have to be the same. > > 6.10.1p3: "The resulting tokens compose the controlling constant > expression which is evaluated according to the rules of 6.6, except > that all signed integer types and all unsigned integer types act as if > they have the same representation as, respectively, the types intmax_t > and uintmax_t defined in the header <stdint.h>." > > 6.6p11: "The semantic rules for the evaluation of a constant expression > are the same as for nonconstant expressions." > > Im quite optimistic that, in year 18 after ISO C, pre-standard > preprocessors have fallen into disuse :-) >
They are supposed to be and likely are the same. I know at least one commercial compiler that has the preprocessor right and the run time wrong. It was released by a company that should know better and has been doing this for quite a few years. Their license doesn't allow benchmark information to be released without their permission. w..
Hans-Bernhard Br&#4294967295;ker wrote:
> CBFalconer wrote: >> Nils wrote: >> ... snip ... >>> int ArithmeticShiftRight (int value, unsigned int shift) { >>> if (shift) { >>> /* Get unsigned version of value to work with */ >>> unsigned int x = (unsigned int) value; >> >> This operation is not possible in a standard C system. > > Oh, but it is. Casting from signed to unsigned operates modulo > (UINT_MAX+1) (C99 6.3.1.3p2).
I know that, but I didn't write that. I suspect I snipped in the wrong places. Yes, my above answer is nonsense.
> > It's the other way round that isn't well-defined. The result of casting > an unsigned number above INT_MAX to integer is implementation-defined. > >> Think about what would happen to negative values in sign-magnitude, >> 1's complement, or 2's complement. > > The same thing. The conversion is independent on representation.
Same silly reply from me. Sorry for the foul-up. -- [mail]: Chuck F (cbfalconer at maineline dot net) [page]: <http://cbfalconer.home.att.net> Try the download section. ** Posted from http://www.teranews.com **
Chris H wrote:
> <cbfalconer@yahoo.com> writes >> Richard Phillips wrote: >> >>... snip ... >>> >>> The problem is there is some misunderstanding here. MISRA lists >>> it's rules as "recommended" and "required" (or something like >>> that), which makes it sound like "required" rules MUST be obeyed, >>> which doesn't appear to be the case from what I now understand. >> >> The only 'required' rules are those of the C standard. > > Absolutely NOT. (Which C standard? )
Since MISRA is organized around C90/95, that standard. -- [mail]: Chuck F (cbfalconer at maineline dot net) [page]: <http://cbfalconer.home.att.net> Try the download section. ** Posted from http://www.teranews.com **
David Brown wrote:
> CBFalconer wrote: >> Steve at fivetrees wrote: >>
... snip ...
>> >>> Summary: avoiding goto as a design concept is a Good Thing. >>> Avoiding gotos as a means of implementing good structure is >>> simply misunderstanding the point. I've seen (possibly on this >>> ng) someone defending goto on the basis that CPUs only know >>> about branches and jumps anyway. Follocks. >> >> Not according to me. Consider the following function outline: >> >> int foo( /* whatever */ ) { >> int errmk = 0; >> FILE *f1, *f2, *fw; >> >> if (!(f1 = fopen(f1name, "r")) { >> errmk = 1; goto f1bad; >> } >> else if (!(f2 = fopen(f2name, "r")) { >> errmk = 2; goto f2bad; >> } >> else if (!(fw = fopen(fwname, "w")) { >> errmk = 3; goto fwbad; >> } >> else { >> /* files open, play appropriate games */ >> } >> fputs(fwendln, fw); >> fclose(fw); >> fwbad: >> fclose(f2); >> f2bad: >> fclose(f1); >> f1bad: >> return errmk; >> } >> >> There are lots of undetected errors left, that is an outline. >> Yes, there are other ways to handle it. > > int foo( /* whatever */ ) { > int errmk = 0; > FILE *f1, *f2, *fw; > > if (!(f1 = fopen(f1name, "r")) errmk = 1; > else { > if (!(f2 = fopen(f2name, "r")) errmk = 2; > else { > if (!(fw = fopen(fwname, "w")) errmk = 3; > else { /* Files open */ > fputs(fwendln, fw); > fclose(fw); > }; > fclose(f2); > }; > fclose(f1); > }; > return errmk; > }
(I have taken liberties reformatting your quote above.) Well, I did say mine was an outline. In practice I would probably write that the way you did. I guess I wasn't too clear, but I was trying to illustrate a clear way of using goto with forward jumps. I'm lazy and don't use it, but I consider goto clearer than break. -- [mail]: Chuck F (cbfalconer at maineline dot net) [page]: <http://cbfalconer.home.att.net> Try the download section. ** Posted from http://www.teranews.com **
On Fri, 25 Apr 2008 00:33:31 -0400, Robert Adsett wrote:

> Echoing the question. What do you need them for that's not covered by a > divide by a power of 2?
I can't speak for the original poster, but for some signal processing applications, arithmetic-right-shift as a 'division by power of two' is better than an explicit actual division by a power of two *because* of the consistent round-to-negative-infinity behaviour. Round-towards-zero, which is the standard for signed integer division in C, produces an uneven quantization interval around zero, compared to that between all other adjacent integers. This results in significantly (3dB RMS) more noise than properly-rounded ASR, unless you go to the bother of adding a negative rounding constant when the number is negative. Cheers, -- Andrew
On Fri, 25 Apr 2008 18:15:15 -0400, CBFalconer wrote:

> Yes, you are, but no, he's not. Shifts on negative values are undefined > behaviour on any system.
Only in C. They're well defined by the processor architecture manuals of all processors that provide them, and that I am aware of. Probably many others besides. What's more, these behaviours are, in my experience, consistent. Since we're all some-time assembly language programmers here in c.a.e, I am not at all surprised that we bridle that expected behaviour is not supported by the standard. I know that it bugs me. Cheers, -- Andrew
In message <4813D6BF.86BBEF32@yahoo.com>, CBFalconer 
<cbfalconer@yahoo.com> writes
>Chris H wrote: >> <cbfalconer@yahoo.com> writes >>> Richard Phillips wrote: >>> >>>... snip ... >>>> >>>> The problem is there is some misunderstanding here. MISRA lists >>>> it's rules as "recommended" and "required" (or something like >>>> that), which makes it sound like "required" rules MUST be obeyed, >>>> which doesn't appear to be the case from what I now understand. >>> >>> The only 'required' rules are those of the C standard. >> >> Absolutely NOT. (Which C standard? ) > >Since MISRA is organized around C90/95, that standard.
Then you have a complete lack of understanding of the subject and the standards. -- \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ \/\/\/\/\ Chris Hills Staffs England /\/\/\/\/ \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/