Friday, February 22, 2013

Experience on ‘void’ and ‘extern’

Fortunately, after very long time, I am able to have something new in my techblog. It is because of my stay @ onsite and change in the nature of work.

Since few months, may be from August 2012, I am working on brand new thing which I never worked before, never heard before. Really this is the advantage of Service Companies. In these days, I have come across many new things, even though they are small. But it was good to know. I will try to remember as many as possible.

Since I am working Vehicle Diagnostics, except Programming language, everything is new. CAN, CANoe, Renesas's High-Performance Embedded Workshop IDE (HEW), uITRON OS Platform, Flashing Tool, 16-bit co-processor HW platform etc..

When I was using HEW, I came across the wondering behavior of Renesas compiler. For absence of function prototype also, it was giving linker error. I was the first strange thing I faced with HEW/Renesas compiler.

'void' at declaration and call:

When writing one function, I declared as void for function argument. But in the same way, I copied the same prototype in the place of call.

void function (void);
Init()
{
funcrtion(void);
}

Then I got an ERROR message after the compilation. The error was

C2766 (E) parse error at near 'void'

I really took around 30 mins of time to root cause this error. As copied the prototype in place of call, 'void ' was placed as a parameter to that function. This was the reason the above error. When we declare any functions, 'void' will behave in usual way. But when we keep the same in call as a parameter, the meaning of 'void' data type, as we use only void pointers. Looks simple, but new for me.

'extern' without datatype:

As I am working with few KBs of RAM, we used many ‘extern’ to refer the variables shared between files of same module. When I copied the data from extern variable to local array, I could see different data. Say array a[4] = {1,2,3,4} and dest[4] is {1,3}. Once again I started thinking about junk platform or junk IDE kind of thoughts.

/* In one of the source file */
unsigned char a[4];


/* In another source file */
extern a[];

b[0] = a[0];
b[1] = a[1];
b[2] = a[2];
b[3] = a[3];

After the last line of execution, a was {1,2,3,4} and b is {1,3}. After some analysis, I understood the behavior.  I changed the above code as below.

/* In one of the source file */
unsigned char a[4];

/* In another source file */
extern unsigned char a[];

Here, there was no data type associated with the variable, it was  (array 'a') treated as 16-bit data as MCU was 16-bit and hence 0th byte and 2nd byte only copied from the source array.

Same kind of thing happened to me in different way.
There was a 2D array of around 20 indexes and each of 25 bytes, in other module.

const char twodarray[21][25];

I referred this 2D array as extern.

extern const char twodarray[][25];

I was copying the data in my module's init function to my local array like

U8 localArray[25];
strcpy( localArray, twodarray[3] );

It was working fine for few days. But after some time, when we tested, only 4 bytes of data being copied to the destination array. I was wondering and took few hours of time to root cause.

The main definition of the array got changed to

const char twodarray[21][30];

As it was externed as 25 bytes of array, for the strcpy function, array was behaving like twodarray[21][25] only, even though it’s original declaration having 30. When I changed to

extern const char twodarray[][30], it worked fine.

The reasons for this, i think, irrespective of the dimension of the array, all are contiguous memory. Due to this, expected chunk of data was not referenced.

Really I was happy when I could root cause these kind of issues.