Showing posts with label C. Show all posts
Showing posts with label C. Show all posts

Sunday, August 14, 2011

Rounding up!

Right shifting of positive integers leads to truncation:

9 >> 1
4
9 >> 2
2

Interestingly, right shift for negative integers also leads to truncation:

-9 >> 1
-5
-9 >> 2
-3

If we combine the effects, we can get rounding up during right shift for positive integers:

-(-9 >> 1)
5
-(-9 >> 2)
3

So here is a C function for rounding up while shifting:

int rightShiftRoundUp(int x, int n){
    return - ( -x >> n);
}

Voila!

Tuesday, August 9, 2011

How to force your fellow members to use your version of a library function

So you designed your own powerful and scalable and efficient version of malloc and named it my_malloc. Now you wish to make sure that everybody in your team uses this version of malloc rather than calling the standard C library version. How would you enforce that?

#undef  malloc
#define malloc use_my_malloc_please


You just put the above code in a common header file for your project which gets included everywhere. Anybody who tries to use standard library malloc, will get a compilation error. Hmm, this is only if  you are a C style programmer. In C++ off course you can override new and delete operators for a class as well as introduce your own new handlers.

Offset of an attribute within a structure

Sometimes we may need to find out the offset of a particular attribute F of a structure T in C. Here is a simple one line macro to achieve the same:
  1: # define offsetof(T, F) ((unsigned int)((char *)&((T *)0)->F))


To understand, we are typecasting address NULL to type T and then computing the address of field F. Since the compiler knows about the layout of type T, hence it can compute this value during compilation and fill in wherever this is required. This is not computed at run-time.




Monday, August 8, 2011

Clamping short to unsigned char

Here is a standard video processing problems. Your 8-bit pixel values are typically in the range 0-255. If you do some processing on them which lead their values of this range you need to bring them down to this range. Negative values are clamped to 0 while positive values greater than 255 are clamped to 255.

A typical unoptimized implementation looks like follows.

  1: unsigned char clamp(short value){
  2:   if (value < 0) return 0;
  3:   if (value > 0xff) return 0xff;
  4:   return value;
  5: }


After long time, today I ended up seeing a much nicer implementation in FFmpeg code base which basically looks like:.






  1: const unsigned char clamp(int a)
  2: {
  3:   if (a&(~0xFF)) return (-a)>>31;
  4:   else return a;
  5: } 






And I think, with a single if statement, its wonderful!


Sunday, August 7, 2011

Functional programming and GCC

I was surprised to find that its possible in GCC to specify whether a function is pure or not at compile time. A pure function is a function which has no side effects. i.e. Its output depends solely on its input arguments and it doesn't affect any other resource in the system.

GCC allows one to specify function attributes. There is a specific attribute "pure" to specify pure function. E.g.: Publish Post

int square (int) __attribute__ ((pure));
Essentially this helps in doing specific compiler optimization (common sub-expression elimination). E.g. If a piece of code calls square(2)*square(2), compiler can rewrite it in such a way that square(2) is called once and the computed value is reused in place of second call to square(2).

Functions like strlen and memcpy are very good examples of pure functions. While flose(), feof() [in a multi-threading environment], a function which may lead to an infinite loop are all examples of non-pure functions.

This is covered in detail at Function Attributes in GCC.