CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

The insidious abs() function

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
gribas



Joined: 21 Feb 2008
Posts: 21

View user's profile Send private message

The insidious abs() function
PostPosted: Tue Aug 14, 2012 7:39 am     Reply with quote

Hi,

Code:

void main() {
   int8 a,b,delta;
   a = 1;
   b = 2;
   delta = abs(a-b);
   printf("Delta abs(1-2) = %u \r\n",delta);
}


The result of course is not 1, but somehow I think it should be. I could not find the abs() function prototype inside the header files but from the help it gave me the impression that the parameter was treated as a signed value. The code below works.


Code:

int8 my_abs(signed int8 value) {
  return abs(value);
}

void main() {
   int8 a,b,delta;
   a = 1;
   b = 2;
   delta = my_abs(a-b);
   printf("Delta my_abs(1-2) = %u \r\n",delta);
}


Regards,
sseidman



Joined: 14 Mar 2005
Posts: 159

View user's profile Send private message

PostPosted: Tue Aug 14, 2012 7:55 am     Reply with quote

Try typecasting your operation inside the abs function.
Ttelmah



Joined: 11 Mar 2010
Posts: 19538

View user's profile Send private message

PostPosted: Tue Aug 14, 2012 8:14 am     Reply with quote

1-2 (unsigned int8 arithmetic) gives binary 11111111.

at sseidman has said, cast one of more of the values to signed before the subtraction.

delta=abs((signed)a-b);

ABS is just a macro, not a function.

Basically

#define abs(x) (x<0)?-x:x

if you call it with two unsigned values it does it's maths with their type, and signe they can never be <0, returns the overflowed result....


Best Wishes
gribas



Joined: 21 Feb 2008
Posts: 21

View user's profile Send private message

PostPosted: Tue Aug 14, 2012 8:43 am     Reply with quote

Hi,

I don't see how the value is treated as signed inside the function abs(). If that was the case it should work like my_abs() does. From my perspective I'm feeding the abs() function with the (one byte) value 0xFF. This value can be read as 255 or -1.

My point is that the abs() function should always treat its parameter as a signed parameter. I fail to see a situation where one would intentionally call abs() with an unsigned value.

Is it straightforward to you that the correct way to use the abs() should always be abs((signed)(x))?

Regards,
Ttelmah



Joined: 11 Mar 2010
Posts: 19538

View user's profile Send private message

PostPosted: Tue Aug 14, 2012 9:12 am     Reply with quote

The point is that it is _not a function_. Very key thing to understand. It is just a macro.
A function causes automatic type casting to it's defined type(s). A macro does _nothing_. This is why abs will work with any variable type (float, long, integer, etc. etc.), but whether it has any _meaning_ is dependant on the types of the variables.
Your 'wrapper function', automatically casts the variables to 'signed', so they start working. Without this, two unsigned values, no casting, so result<0, can never be 'true', so abs does not work.
The same is true of abs in most C's, _but_ in most C's, the default integer type is 'signed', so by default it works.

Best Wishes
sseidman



Joined: 14 Mar 2005
Posts: 159

View user's profile Send private message

PostPosted: Tue Aug 14, 2012 9:30 am     Reply with quote

gribas wrote:

My point is that the abs() function should always treat its parameter as a signed parameter. I fail to see a situation where one would intentionally call abs() with an unsigned value.


My experience is that c compilers do exactly what you ask them to do without stopping to make sure it makes sense. You can make mistakes either way with abs(). The way you want it to behave will create bad results when the MSB is 1 for one of your operands.

FWIW, some of my most frequent errors involve data types and casting, and they tend to be hard to debug for me. It's taught me to be real careful about specifically casting when I have any questions. I suppose I could also just learn the rules about type conversions like the back of my hand, but try as I might, I often mess that up.
gribas



Joined: 21 Feb 2008
Posts: 21

View user's profile Send private message

PostPosted: Tue Aug 14, 2012 10:04 am     Reply with quote

Hi,

Thanks a lot for your remarks. Ttelmah, I could not find the original ccs macro definition so I modified your's a little:

Code:

#define abs2(x) (((signed)(x)) <0)?-(x):(x)

void main() {
   int8 a,b;
   a = 1;
   b = 2;
   printf("abs2(1-2) = %u \r\n",abs2(a-b));
}


It works, but I'll keep using the "abs((signed)a-b)" version as a reminder to always check the data types. =)


Regards,
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Tue Aug 14, 2012 3:45 pm     Reply with quote

Quote:
ABS is just a macro, not a function.

Sounds plausible at first sight. But apparently it isn't defined as a macro anywhere in CCS include files. It
seems to be a built-in function. Or did I miss something?

K&R 2nd edition says it's an integer function with integer argument that belongs to stdlib. Consequently many
compilers implement it with an implicit typecast to int, e.g. Borland C or MSVC. Thus the expectation in the
original post isn't far fetched.
Ttelmah



Joined: 11 Mar 2010
Posts: 19538

View user's profile Send private message

PostPosted: Wed Aug 15, 2012 1:20 am     Reply with quote

Two things:
Remember that in CCS C, an int is unsigned. This then leads to the rest of the behaviour, and the 'expectation' being wrong, whether it is a function, or a macro. This is the 'key thing to remember'.
However If you look in the existing include files, you will find labs, and fabs, both being #defined to just use abs. This will only work, if it is a macro. In CCS, it is I believe, an implicit macro (one defined inside the compiler, rather than in the includes).

Best Wishes
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Wed Aug 15, 2012 2:59 am     Reply with quote

Quote:
Remember that in CCS C, an int is unsigned. This then leads to the rest of the behaviour.

Yes, if we assume that the C stdlib integer function has been implemented without much thinking.

By the way, the abs() behaviour is identical (like a macro) in PCD that has a signed integer type.

Personally, I don't have much expectations about the implementation of the C standard in CCS C. I just meaned to mention that the OP's expectation has some reasoning.

I agree to your consideration about labs(), although I don't know how an implicite macro in CCS C looks like. I imagine, that it's more powerful than a dumb preprocessor macro and can e.g. implement a typecast to different signed types.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group