By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
428,558 Members | 1,607 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 428,558 IT Pros & Developers. It's quick & easy.

Confirm this is Standard code

P: n/a
I've got two bits of code that I would like some more experienced folks
to check for conformance to the Standard. I've tried my best to read
the standard and search around and I think and hope this code contains
no cause for concern.

/* taking absolute value of signed integer */
int32 val;
uint32 abs_val;

val = -492;

if(val < 0)
abs_val = -(uint32)val;

I have done my reading of the standard on this and searching around and
it seems the above is fine by the standard. Just want to make sure
because my lint warns about "Expected signed type".
Also please look at the code below and tell me if there is anything to
worry about as far as being non-standard. Just a note, the absolute
value of shiftAmt has already been pre-conditioned and is guaranteed
not to overflow an int16 so don't warn me about that possibly
overflowing and resulting in U.B..

int32 foo(int16 x, int16 shiftAmt)
{
int32 ret;

...
/* code block dealing with x < 0, shiftAmt < 0 */
ret = -((int32)((-(uint32)x) << (-shiftAmt)));
}

Thanks.

Nov 14 '05 #1
Share this Question
Share on Google+
18 Replies


P: n/a
On 2 Apr 2005 14:09:21 -0800, "joshc" <jo********@gmail.com> wrote in
comp.lang.c:
I've got two bits of code that I would like some more experienced folks
to check for conformance to the Standard. I've tried my best to read
the standard and search around and I think and hope this code contains
no cause for concern.
What puzzles me is WHY you want to write code like this.
/* taking absolute value of signed integer */
int32 val;
uint32 abs_val;

val = -492;

if(val < 0)
abs_val = -(uint32)val;
Why not just:

abs_val = abs(val);

....after including <stdlib.h>? Or just:

abs_val = val > 0 ? val : -val;

In any case, the result of the code is well-defined if val is negative
unless it happens to be the minimum possible value and has a magnitude
of on greater than the maximum positive value.
I have done my reading of the standard on this and searching around and
it seems the above is fine by the standard. Just want to make sure
because my lint warns about "Expected signed type".

Also please look at the code below and tell me if there is anything to
worry about as far as being non-standard. Just a note, the absolute
value of shiftAmt has already been pre-conditioned and is guaranteed
not to overflow an int16 so don't warn me about that possibly
overflowing and resulting in U.B..
Pre-conditioned to be what? Since you are casting to a 32 bit type
before the shift, and returning a 32 bit value, what might overflow a
16 bit type doesn't make any difference.
int32 foo(int16 x, int16 shiftAmt)
{
int32 ret;

...
/* code block dealing with x < 0, shiftAmt < 0 */
ret = -((int32)((-(uint32)x) << (-shiftAmt)));
If shiftAmt was between 0 and -31 inclusive, this has well defined
results but looks quite bizarre. If shiftAmt is positive or less than
-32, it has undefined results.
}

Thanks.


Can you describe in words exactly what it is you are trying to do with
this code? Whatever it is, I am pretty sure that there is a much less
convoluted way to write it.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
Nov 14 '05 #2

P: n/a
In article <11**********************@g14g2000cwa.googlegroups .com>,
joshc <jo********@gmail.com> wrote:
/* taking absolute value of signed integer */
int32 val;
uint32 abs_val;

val = -492;

if(val < 0)
abs_val = -(uint32)val;


Would the cast not be processed before the unary minus? I could be wrong
but that code -looks- to me to be doing the following:

1) take a negative number and make it into an unsigned value
(I would have to re-read the standard to see what it says
about exactly what would happen)
2) does a unary minus on the unsigned value
(I would have to re-read the standard to see what unary minus
means when applied to an unsigned value)
3) sees that the value is to be assigned to an unsigned value, so
potentially converts the value again.

It would make more sense to me if the code were

if(val < 0)
abs_val = (uint32)(-val);

at which point the cast would merely be redundant, with no
possibility of a triple conversion.
--
Would you buy a used bit from this man??
Nov 14 '05 #3

P: n/a
Jack Klein wrote:
On 2 Apr 2005 14:09:21 -0800, "joshc" <jo********@gmail.com> wrote in
comp.lang.c:
Why not just:

abs_val = abs(val);
This is code for an embedded system, i.e a freestanding implementation.

Pre-conditioned to be what? Since you are casting to a 32 bit type
before the shift, and returning a 32 bit value, what might overflow a
16 bit type doesn't make any difference.
int32 foo(int16 x, int16 shiftAmt)
{
int32 ret;

...
/* code block dealing with x < 0, shiftAmt < 0 */
ret = -((int32)((-(uint32)x) << (-shiftAmt)));
If shiftAmt was between 0 and -31 inclusive, this has well defined
results but looks quite bizarre. If shiftAmt is positive or less

than -32, it has undefined results.


Yeah, pre-conditioned to ensure what you describe above(0 to -31).

Thanks.

Nov 14 '05 #4

P: n/a

Walter Roberson wrote:
In article <11**********************@g14g2000cwa.googlegroups .com>,
joshc <jo********@gmail.com> wrote:
/* taking absolute value of signed integer */
int32 val;
uint32 abs_val;

val = -492;

if(val < 0)
abs_val = -(uint32)val;
Would the cast not be processed before the unary minus? I could be

wrong but that code -looks- to me to be doing the following:

1) take a negative number and make it into an unsigned value
(I would have to re-read the standard to see what it says
about exactly what would happen)
2) does a unary minus on the unsigned value
(I would have to re-read the standard to see what unary minus
means when applied to an unsigned value)
3) sees that the value is to be assigned to an unsigned value, so
potentially converts the value again.

It would make more sense to me if the code were

if(val < 0)
abs_val = (uint32)(-val);

at which point the cast would merely be redundant, with no
possibility of a triple conversion.
--
Would you buy a used bit from this man??

Basically the reason I do this is so that I don't get signed integer
overflow because that results in undefined behavior. On the other hand,
dealing with unsigned integers there is no overflow and all arithmetic
operations are performed mod UINT_MAX+1 or whatever the relevant limit
is.

Nov 14 '05 #5

P: n/a
On Sat, 02 Apr 2005 23:46:46 +0000, Walter Roberson wrote:
In article <11**********************@g14g2000cwa.googlegroups .com>,
joshc <jo********@gmail.com> wrote:
/* taking absolute value of signed integer */
int32 val;
uint32 abs_val;

val = -492;

if(val < 0)
abs_val = -(uint32)val;
Would the cast not be processed before the unary minus?


That seems to be the intent.
I could be wrong
but that code -looks- to me to be doing the following:

1) take a negative number and make it into an unsigned value
(I would have to re-read the standard to see what it says
about exactly what would happen)
It says the result is the value you get by adding one more than the
largest value representable in the unsigned type. Call that largest value
UINT32_MAX then the result is aritmetically val + UINT32_MAX+1.
-(uint32)val is then -val-(UINT32_MAX+1). To bring that back into
a representable value when it is negative we must add UINT32_MAX+1 again
giving -val-(UINT32_MAX+1)+(UINT32_MAX+1) i.e. -val. This gives us the
result we want as an unsigned value. The only situation where this "fails"
is when the absolute value of val is not representable as a uint32, in
that case the result turns out to be zero. That's unlikely because
unsigned types usually have a larger positive range then their
corresponding signed types.
2) does a unary minus on the unsigned value
(I would have to re-read the standard to see what unary minus
means when applied to an unsigned value)
3) sees that the value is to be assigned to an unsigned value, so
potentially converts the value again.

It would make more sense to me if the code were

if(val < 0)
abs_val = (uint32)(-val);

at which point the cast would merely be redundant, with no
possibility of a triple conversion.


The problem here is that -val can result in undefined behaviour which is
what the code is trying to avoid.

Lawrence
Nov 14 '05 #6

P: n/a
In article <pa***************************@netactive.co.uk>,
Lawrence Kirby <lk****@netactive.co.uk> wrote:
Would the cast not be processed before the unary minus?
That seems to be the intent.


Thanks for the detailed explanation, Lawrence
if(val < 0)
abs_val = (uint32)(-val);

The problem here is that -val can result in undefined behaviour which is
what the code is trying to avoid.


If I understand correctly, the undefined behaviour would be at
the boundary condition, where val is the most negative value.
Perhaps special case that particular value?

if (val == INT32_MIN) abs_val = 0;
else if (val < 0) abs_val = -val;
else abs_val = val;

--
Walter Roberson is my name,
And Usenet is my nation.
Cyber space is my dwelling pace,
And flames my destination.
Nov 14 '05 #7

P: n/a
On 2 Apr 2005 15:50:44 -0800, "joshc" <jo********@gmail.com> wrote in
comp.lang.c:
Jack Klein wrote:
On 2 Apr 2005 14:09:21 -0800, "joshc" <jo********@gmail.com> wrote in
comp.lang.c:
Why not just:

abs_val = abs(val);


This is code for an embedded system, i.e a freestanding implementation.


I understand all about embedded systems, that what I've been doing for
25 years.

Pre-conditioned to be what? Since you are casting to a 32 bit type
before the shift, and returning a 32 bit value, what might overflow a
16 bit type doesn't make any difference.
int32 foo(int16 x, int16 shiftAmt)
{
int32 ret;

...
/* code block dealing with x < 0, shiftAmt < 0 */
ret = -((int32)((-(uint32)x) << (-shiftAmt)));


If shiftAmt was between 0 and -31 inclusive, this has well defined
results but looks quite bizarre. If shiftAmt is positive or less

than
-32, it has undefined results.


Yeah, pre-conditioned to ensure what you describe above(0 to -31).

Thanks.


I still don't understand why you are writing code this way. Why have
you written the code in such an unusual and complex manner?

Again, post an explanation of what it is you are trying to do, what
the values are and what you need to do to them. There must be a
simpler way to write code to do what you need.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
Nov 14 '05 #8

P: n/a
Walter Roberson wrote:
Lawrence Kirby <lk****@netactive.co.uk> wrote:
if(val < 0)
abs_val = (uint32)(-val);


The problem here is that -val can result in undefined behaviour
which is what the code is trying to avoid.


If I understand correctly, the undefined behaviour would be at
the boundary condition, where val is the most negative value.
Perhaps special case that particular value? ...


Or find a (big-picture) algorithm that doesn't require the
magnitude of a signed int in the first place.

--
Peter

Nov 14 '05 #9

P: n/a

Jack Klein wrote:
On 2 Apr 2005 15:50:44 -0800, "joshc" <jo********@gmail.com> wrote in
comp.lang.c:
Jack Klein wrote:
On 2 Apr 2005 14:09:21 -0800, "joshc" <jo********@gmail.com> wrote in comp.lang.c:
Why not just:

abs_val = abs(val);
This is code for an embedded system, i.e a freestanding implementation.
I understand all about embedded systems, that what I've been doing for 25 years.
Heh, sorry, I didn't mean it to sound the way you took it. I don't have
25 years experience and that's why I am asking these questions :).

Pre-conditioned to be what? Since you are casting to a 32 bit type before the shift, and returning a 32 bit value, what might overflow a 16 bit type doesn't make any difference.

> int32 foo(int16 x, int16 shiftAmt)
> {
> int32 ret;
>
> ...
> /* code block dealing with x < 0, shiftAmt < 0 */
> ret = -((int32)((-(uint32)x) << (-shiftAmt)));

If shiftAmt was between 0 and -31 inclusive, this has well defined results but looks quite bizarre. If shiftAmt is positive or less

than
-32, it has undefined results.


Yeah, pre-conditioned to ensure what you describe above(0 to -31).

Thanks.


I still don't understand why you are writing code this way. Why have
you written the code in such an unusual and complex manner?

Again, post an explanation of what it is you are trying to do, what
the values are and what you need to do to them. There must be a
simpler way to write code to do what you need.


If you want the whole story I can tell you offline. Let me know.

Nov 14 '05 #10

P: n/a
joshc wrote:
Jack Klein wrote:

.... snip ...

I still don't understand why you are writing code this way. Why
have you written the code in such an unusual and complex manner?

Again, post an explanation of what it is you are trying to do,
what the values are and what you need to do to them. There must
be a simpler way to write code to do what you need.


If you want the whole story I can tell you offline. Let me know.


No, you are the one who wants help. Jack is telling you to explain
what you are trying to do, and you may get some help. Simply
squalling that you want to square the circle won't go far. You may
get told that your objectives are off-topic, but that doesn't seem
likely in this case.

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
Nov 14 '05 #11

P: n/a
On Sun, 03 Apr 2005 17:02:55 +0000, Walter Roberson wrote:
In article <pa***************************@netactive.co.uk>,
Lawrence Kirby <lk****@netactive.co.uk> wrote:
Would the cast not be processed before the unary minus?
That seems to be the intent.


Thanks for the detailed explanation, Lawrence
if(val < 0)
abs_val = (uint32)(-val);

The problem here is that -val can result in undefined behaviour which is
what the code is trying to avoid.


If I understand correctly, the undefined behaviour would be at
the boundary condition, where val is the most negative value.


That is the problem case, specifically when INT32_MIN has a greater
magnitude than INT32_MAX.
Perhaps special case that particular value?

if (val == INT32_MIN) abs_val = 0;
Better would be if (val < -INT32_MAX) because C doesn't require minimum
values to have a larger magnitude than maximum ones.
else if (val < 0) abs_val = -val;
else abs_val = val;


This is more complex and probably less efficient which might be relevant
to some people. abs_val = (uint32)(-val); produces the correct value
(rather than 0) for INT32_MIN if uint32 can represent it. Once you see
what it is doing this is a simple and clean solution to the problem. It
can produce an incorrect result (0) in rare to non-existant
circumstances when the correct result is not representable, but it
doesn't have any undefined behaviour.

Lawrence
Nov 14 '05 #12

P: n/a

CBFalconer wrote:
joshc wrote:
Jack Klein wrote:

... snip ...

I still don't understand why you are writing code this way. Why
have you written the code in such an unusual and complex manner?

Again, post an explanation of what it is you are trying to do,
what the values are and what you need to do to them. There must
be a simpler way to write code to do what you need.


If you want the whole story I can tell you offline. Let me know.


No, you are the one who wants help. Jack is telling you to explain
what you are trying to do, and you may get some help. Simply
squalling that you want to square the circle won't go far. You may
get told that your objectives are off-topic, but that doesn't seem
likely in this case.


My question has already been answered so that indicates that the
information I gave was sufficient for people to address the question. I
just wanted someone to confirm that was standard C and wasn't really
looking for advice on how to "better" write my algorithm.

Anyhow, since people seem interested, what that code is part of is a
fixed-point subtraction routine. I need to subtract an unsigned
fixed-point number from a signed fixed-pt number. In particular, in
that "odd" looking code, int16 x is the signed fixed-point number which
I am trying to scale to match the radix point position of the other
operand. Please don't ask me why signed and unsigned types are involved
in the subtraction, that is beyond my control and I also think it's
stupid.

Thanks for your help.

Nov 14 '05 #13

P: n/a

Lawrence Kirby wrote:
On Sun, 03 Apr 2005 17:02:55 +0000, Walter Roberson wrote:
snip...
The problem here is that -val can result in undefined behaviour which iswhat the code is trying to avoid.


If I understand correctly, the undefined behaviour would be at
the boundary condition, where val is the most negative value.


That is the problem case, specifically when INT32_MIN has a greater
magnitude than INT32_MAX.
Perhaps special case that particular value?

if (val == INT32_MIN) abs_val = 0;


Better would be if (val < -INT32_MAX) because C doesn't require

minimum values to have a larger magnitude than maximum ones.
else if (val < 0) abs_val = -val;
else abs_val = val;
This is more complex and probably less efficient which might be

relevant to some people. abs_val = (uint32)(-val); produces the correct value
(rather than 0) for INT32_MIN if uint32 can represent it. Once you see what it is doing this is a simple and clean solution to the problem. It can produce an incorrect result (0) in rare to non-existant
circumstances when the correct result is not representable, but it
doesn't have any undefined behaviour.


Lawrence, I'm a little confused by what seems to me to be a disparity
between what you said a few posts above and what you say in this post.
In this post you say that abs_val = (uint32)(-val) doesn't have any
undefined behavior. I thought you confirmed a few posts above that it
_does_ have undefined behavior if val=INT32_MIN and abs(INT32_MIN) >
INT32_MAX.

I may be misunderstanding your post so please clarify.

Thanks.

Nov 14 '05 #14

P: n/a
Lawrence Kirby wrote:
.... snip ...
This is more complex and probably less efficient which might be
relevant to some people. abs_val = (uint32)(-val); produces the
correct value (rather than 0) for INT32_MIN if uint32 can
represent it. Once you see what it is doing this is a simple and
clean solution to the problem. It can produce an incorrect result
(0) in rare to non-existant circumstances when the correct result
is not representable, but it doesn't have any undefined behaviour.


Except that "(uint32)(-val)" for val == INT_MIN should produce the
value 0 for the normal value of UINT_MAX.

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
Nov 14 '05 #15

P: n/a

Jack Klein wrote:
What puzzles me is WHY you want to write code like this.

On 2 Apr 2005 14:09:21 -0800, "joshc" <jo********@gmail.com> wrote in
comp.lang.c:
/* taking absolute value of signed integer */
int32 val;
uint32 abs_val;

val = -492;

if(val < 0)
abs_val = -(uint32)val;
Why not just:

abs_val = abs(val);

...after including <stdlib.h>? Or just:

abs_val = val > 0 ? val : -val;

In any case, the result of the code is well-defined if val is

negative unless it happens to be the minimum possible value and has a magnitude of on greater than the maximum positive value.
I suppose he tried to avoid exactly your "unless" case.

I have done my reading of the standard on this and searching around and it seems the above is fine by the standard. Just want to make sure
because my lint warns about "Expected signed type".

Also please look at the code below and tell me if there is anything to worry about as far as being non-standard. Just a note, the absolute
value of shiftAmt has already been pre-conditioned and is guaranteed not to overflow an int16 so don't warn me about that possibly
overflowing and resulting in U.B..


Pre-conditioned to be what? Since you are casting to a 32 bit type
before the shift, and returning a 32 bit value, what might overflow a
16 bit type doesn't make any difference.
int32 foo(int16 x, int16 shiftAmt)
{
int32 ret;

...
/* code block dealing with x < 0, shiftAmt < 0 */
ret = -((int32)((-(uint32)x) << (-shiftAmt)));


If shiftAmt was between 0 and -31 inclusive, this has well defined
results but looks quite bizarre. If shiftAmt is positive or less

than -32, it has undefined results.


Is that they are well defined in the sense that they are implementation
defined? Doesn't every argument pair that creates something > INT32_MAX
invoke implementation defined behaviour at the (int32) cast (e.g.
foo(-2,-31))?
BTW, how are integer promotions executed on extended integer types? Are
they left untouched even when an int is wider than a int32_t?

Mark

Nov 14 '05 #16

P: n/a

CBFalconer wrote:
Lawrence Kirby wrote:

... snip ...

This is more complex and probably less efficient which might be
relevant to some people. abs_val = (uint32)(-val); produces the
correct value (rather than 0) for INT32_MIN if uint32 can
represent it. Once you see what it is doing this is a simple and
clean solution to the problem. It can produce an incorrect result
(0) in rare to non-existant circumstances when the correct result
is not representable, but it doesn't have any undefined behaviour.


Except that "(uint32)(-val)" for val == INT_MIN should produce the
value 0 for the normal value of UINT_MAX.


How??? The cast is happening after the negation so I don't see how this
isn't undefined behavior in the case I mentioned where you have
|INT_MIN| > INT_MAX.

Nov 14 '05 #17

P: n/a
joshc wrote:

CBFalconer wrote:
Lawrence Kirby wrote:

... snip ...

This is more complex and probably less efficient which might be
relevant to some people. abs_val = (uint32)(-val); produces the
correct value (rather than 0) for INT32_MIN if uint32 can
represent it. Once you see what it is doing this is a simple and
clean solution to the problem. It can produce an incorrect result
(0) in rare to non-existant circumstances when the correct result
is not representable, but it doesn't have any undefined behaviour.


Except that "(uint32)(-val)" for val == INT_MIN should produce the
value 0 for the normal value of UINT_MAX.


How??? The cast is happening after the negation so I don't see how
this isn't undefined behavior in the case I mentioned where you
have |INT_MIN| > INT_MAX.


You're right. I'm wrong.

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
Nov 14 '05 #18

P: n/a
On 2 Apr 2005 14:09:21 -0800,
joshc <jo********@gmail.com> wrote:

I've got two bits of code that I would like some more experienced folks
to check for conformance to the Standard. I've tried my best to read
the standard and search around and I think and hope this code contains
no cause for concern.

/* taking absolute value of signed integer */
int32 val;
uint32 abs_val;


I would have thought that int32 and uint32 were not standards conform
but int32_t and uint32_t as defined in <stdint.h> are on platform where
such types are supported.

int32 and uint32 could be user defined types in part of the code not
listed, though.

Villy
Nov 14 '05 #19

This discussion thread is closed

Replies have been disabled for this discussion.