Embedded C

Here are some GNU toolchain based C- tricks that will help you in reducing unexpected bugs in your Embedded C code.


#include <stdio.h>

main()
{
    if (sizeof(int) > -1)
        printf("True");
    else
        printf("False");
}

/*
Prints:  False.

Why?

Answer: Interger Promotion...
(sizeof(int) > -1) ==> (4u > -1) ==> (4u > -1u) ==> (4u > -1u) ==> (4u > 4294967295uu) 
 because -1u is equal to 4294967295 in unsigned
 
That's why else statement is executed!
*/

 


 

/* why  */

#if (sizeof(xyz) > 0)
    #error "Error"
#endif

/* fails? */

/*
because #if are pre-processor directive while sizeof operator is evaluated at compile time 
(except in case of VLA). and pre-processors comes first before compiler so at the time of 
pre-processor, there is no information on sizeof output.
*/

 


 

/* 
 You cannot use a function call when initializing a static or global variable: 
*/

/* Example: */

void fun (void) {
    static int x = init_ftn();
}

/* [Error]: initializer element is not constant */

/*
 Alternate approach:
 Error can be avoided by splitting the definition and assignment statments e.g.
*/

static int x;
x = init_ftn();

 


 

/* Never do this: */

int *ptr = (int *) malloc (sizeof (int) * XYZ);

ptr = realloc (ptr, NEW_SIZE);

/*
Because if new size memory could not be alloted, the NULL pointer will be return by realloc; 
thus the address to original allocated memory will be lost. this could lead to memory leak...
*/

 


 

/* sizeof Operator: */

/*
sizeof is always computed at compile time in C89. Since C99 and with the introduction of 
Variable Length Arrays (VLA), it is computed at run time when a variable length array is 
part of the expression in the sizeof operand.

Same for the evaluation of the sizeof operand: it is not evaluated in C89 but in C99 if 
the operand is of variable length array type it is evaluated. For example:
*/

int n = 5;
int x[n];

sizeof (x[n--]); 

// n is now 4

 


 

/*
why free(ptr) doesn't automatically assign NULL to ptr';

This is because pointer here is passed by value not by reference (not as free (**ptr)). 
so free function has no idea about the actual pointer location.
*/

 


 

/*
Retrun of malloc(0)
*/

/*
When malloc is used with an argument of zero, its behavior is "implementation-specific". 
It may return a pointer to NULL or it may return a pointer to a region with zero bytes allocated.

The C standard says:
If the space cannot be allocated, a null pointer is returned. If the size of the space 
requested is zero, the behavior is implementation defined: either a null pointer is 
returned, or the behavior is as if the size were some nonzero value, except that the returned 
pointer shall not be used to access an object.

malloc(0) will return either "a null pointer or a unique pointer that can be successfully 
passed to free()".
*/

 


 

int *pi = (int*) malloc(sizeof(int));

/*
Before the pointer to void was introduced to C, explicit casts were required with malloc 
to stop the generation of warnings when assignments were made between incompatible pointer 
types. Since a pointer to void can be assigned to any other pointer type, explicit casting 
is no longer required. Some developers consider explicit casts to be a good practice.
*/

 


 

/*
calloc vs malloc speed:
*/

/*
The execution of calloc may take longer than using malloc as the memory zeroed out 
before the call to calloc returns.
*/

 


 

/*
To free malloc allocated memory without fucntion free():
*/

int *ptr = malloc(10 * size(int));

realloc (ptr,0);

 


 

/*
free (NULL) as NOP instruction:
*/

/*
The free function causes the space pointed to by ptr to be deallocated, that is, made available 
for further allocation. If ptr is a null pointer, noting  happens like NOP instruction.
*/

 


 

int *ptr = &x;
free (ptr);

/*
If the pointer passed has been allocated by other than a malloc type function, then the 
function’s behavior is undefined. Its a runtime error.
*/

 


 

/*
An attempt to pass the address of an integer literal as shown below will also generate a
syntax error:
*/

passingAddressOfConstants(&amp;23, &amp;23);

/*
In this case, the error message will indicate that an lvalue is required as the address-of
operator’s operand. 
*/

 


 

/*
  typedef is a language construct that associates a name to a type.
  You use it the same way you would use the original type, for instance
*/

typedef int myinteger;
typedef char *mystring;
typedef void (*myfunc)();
  
using them like

myinteger i;   // is equivalent to int i;
mystring s;    // is the same as char *s;
myfunc f;      // compile equally as  void (*f)();

 


 

int a[x];
&amp;a /* pointer to entire array */
a  /* pointer to integer (first element) */

 


 

int *ptr = malloc (sizeof(int));
ptr++;

free (ptr);

/* 
 This is a runtime error because Heap Manager has no entry for this address (incremented address) 
*/

 


 

/* Passing multidimensional array to function, the column size must be specified. e.g. */

void display2DArray(int arr[][5], int rows)

/* or: */

void display2DArray(int (*arr)[5], int rows)  

/*
() is vary important as *arr[5] would be array of pointers not pointer to array.
*/

 


 

/*
 while one dimension array is passed to funciton like:
*/
void fun (int *)

/*
 Two dimensional array can't be passed to function like this...
*/
void fun (int **)

 


 

/*
 When passing array of more than 2-dimension to function all the dimensions except first need to 
be specified:
*/

void display3DArray(int (*arr)[2][4], int rows)

 


 

/*
Array of char vs string array

string is sequence of ASCII char ending with ASCII NUL character while array of char may not 
necessary contain ASCII character (like they may contain numbers < 255) and is not ended with NUL.
*/

 


 

/*
 Character constants (character literals) are character sequences enclosed in single quotes. 
 In C, they are of type int. This is demonstrated as follows:
*/

printf("%d\n",sizeof(char));
printf("%d\n",sizeof('a'));

/*
 When executed, the size of char will be 1 while the character literal’s size will be 4. This
 anomaly is an artifact of the language design.
*/

 


 

/*
 In C++, 
*/
sizeof('a') == sizeof(char) == 1 
/*
This makes intuitive sense, since 'a' is a character literal.
*/
/*
 In C however, 
*/
sizeof('a') == sizeof(int)
/*
That is, it appears that C character literals are actually integers.
*/

 


 

/*
 What is the difference between a String Constant and String Literal in C?
*/

/*
 They are one and the same. Merely a preference in which word you use to describe the string.
 In the C99 Draft from 2007 the term sting literal is used. The term string constant does not appear 
 in the draft at all. Books use the term String Constant, but C99 uses String Literal.
 Similarly Character literals are character constants.
*/

 


 

/*
 You cannot assign a string literal to a char array after its been created:
*/
char a[6];
a = "Hello";

/*
 why this is an error?

This is because a is contant pointer to the first element of array. a = "Hello" means you are assigning 
`a`(contant pointer to array first elment) the starting address of "Hello" String literal i.e. changing 
constant pointer a.
*/

/*
 Similarly consider the following program:
*/

typedef struct{
	char a[6];
}point;

int main (int argc, char *argv[]) {
	
    point p;            //POINT-X
    p.a = "onetwo";	    //POINT-Y
    return 0;
}

/*
The compiler wil through an error at POINT-Y because the array a[6] has already been created at 
POINT-X. same problem described in above. If we replace POINT-X and POINT-Y with:
*/

point p = {"onetwo"};		//POINT-X

/*
The error will go away. This is because we are COPING characters from String Literal to character 
array at the time of creation of array at statement 'point p'. see bellow trick.
*/

 


 

/*
 What is the difference between char s[] and char *s?
*/

/*
 The difference here is that
*/

char *s = "Hello world";

/* 
 Will place "Hello world" in the read-only parts of the memory, and making s a pointer to that
 makes any writing operation on this memory illegal.

While doing:
*/

char s[] = "Hello world";

/*
 puts the literal string in read-only memory and copies the string to newly allocated memory 
 on the stack. Thus making
*/

s[0] = 'J';

/* legal. */

 


 

/* String Pool: */

char *header = (char*) malloc(strlen("Media Player")+1);
strcpy(header,"Media Player");

/*
 Only single copy of string literal will be stored in the String Pool.
*/

 


 

/*
Attempting to initialize a pointer to a char with a character literal will not work. Since 
a character literal is of type int in C, doing so we are actually trying to assign an integer 
to a character pointer. This will cause the application to terminate when the pointer is dereferenced:
*/

char* prefix = '+'; // Illegal

/*
A valid approach using the malloc function follows:
*/

prefix = (char*)malloc(1);
*prefix = '+';

 


 

char command[16];
printf("Enter a Command: ");
scanf("%s",command);
if(command == "Quit") {
    ...
}

/*
 This will evaluate false since we are comparing the address of command array with the 
 string literal’s address.
*/

 


 

char *str = "Hello World";

*(str++) VS *str++ VS (*str)++

/* 
 '*' has lower presedence than ++ so:

 *(str++) == *str++  ==> ++ operator will apply to str first thus post incrementing str.

 (*str)++ is actually trying to increment the dereferenced character (*str) of string literal 
  which will be a run time error.
*/

 


 

/*
 The size of structure is literally equal to sum of data type sizes however the actual size is often larger 
 as padding can occur b/w fields.

 Consider the following example on 64-bits system:
*/

typedef struct{
	char x;  //1-byte
	int y;   //4-bytes
	int *p;  //8-bytes
}point;

int main () {
	printf ("%d", sizeof (point));   //16-bytes (3-bytes are padded after char)
	return 0;
}

 


 

/*
With some (indeed, many) C compilers, you can get away with what's called a 'common' definition of a variable
too. 'Common', here, refers to a technique used in Fortran for sharing variables between source files, using 
a (possibly named) COMMON block. What happens here is that each of a number of files provides a tentative 
definition of the variable. As long as no more than one file provides an initialized definition, then the various 
files end up sharing a common single definition of the variable:
*/

---------------------------------- 

@file1.c

int i;

void inc(void) { i++; }

---------------------------------- 

@file2.c

int i;

void dec(void) { i--; }

---------------------------------- 

@file3.c

#include 

int i = 9;

void put(void) { printf("i = %d\n", i); }
---------------------------------- 

/*

This technique does not conform to the letter of the C standard and the 'one definition rule', but the C 
standard lists it as a common variation on its one definition rule. Because this technique is not always 
supported, it is best to avoid using it, especially if your code needs to be portable. Using this technique, 
you can also end up with unintentional type punning. If one of the files declared i as a double instead of as 
an int, C's type-unsafe linkers probably would not spot the mismatch. If you're on a machine with 64-bit int 
and double, you'd not even get a warning; on a machine with 32-bit int and 64-bit double, you'd probably get 
a warning about the different sizes — the linker would use the largest size, exactly as a Fortran program would 
take the largest size of any common blocks.

This is mentioned in the C standard in informative Annex J as a common extension:

J.5.11 Multiple external definitions

There may be more than one external definition for the identifier of an object, with or without the explicit use of 
the keyword extern; if the definitions disagree, or more than one is initialized, the behavior is undefined (6.9.2).

*/

 


 

/* Conflicting Error: */
extern static void fun (void);

/*
 A symbol can only be either global or static at a time.
*/

 


 

/* Wild Pointer: An uninitialized pointer is called wild pointer. */

 


 

/* Designated Initializers: */

[URL]:= https://gcc.gnu.org/onlinedocs/gcc-3.4.5/gcc/Designated-Inits.html

/* 
In a structure initializer, specify the name of a field to initialize with `.fieldname =' before the element value. 
For example, given the following structure,
*/

struct point { 
              int x;
              int y; 
			  };
			  
/* The following initialization */

struct point p = { .y = yvalue, .x = xvalue };

/* is equivalent to */

struct point p = { xvalue, yvalue };

/* Another syntax which has the same meaning, obsolete since GCC 2.5, is `fieldname:', as shown here: */

struct point p = { y: yvalue, x: xvalue };

/*
The `[index]' or `.fieldname' is known as a designator. You can also use a designator (or the obsolete colon syntax) 
when initializing a union, to specify which element of the union should be used. For example,
*/

union foo { int i; double d; };
     
union foo f = { .d = 4 };

/*
will convert 4 to a double to store it in the union using the second element. By contrast, casting 4 to type union 
foo would store it into the union as the integer i, since it is an integer.
*/

 


 

/*
Using incompatible pointer types will result in a warning:
*/

int (*fptrCompute)(int,int);
int addNumbers(int n1, int n2, int n3) {
    return n1+n2+n3;
}

fptrCompute = addNumbers;
/*
The warning follows:
warning: assignment from incompatible pointer type
*/

 


 

/* Casting to Union: */

[URL]:= https://gcc.gnu.org/onlinedocs/gcc-3.4.5/gcc/Cast-to-Union.html#Cast-to-Union

/*
A cast to union type is similar to other casts, except that the type specified is a union type. You can specify 
the type either with union tag or with a typedef name. A cast to union is actually a constructor though, not a cast, 
and hence does not yield an lvalue like normal casts.

The types that may be cast to the union type are those of the members of the union. Thus, given the following union 
and variables:
*/

union foo { int i; double d; };
int x;
double y;

/*
both x and y can be cast to type union foo.

Using the cast as the right-hand side of an assignment to a variable of union type is equivalent to storing in a 
member of the union:
*/

union foo u;
/* ... */
u = (union foo) x  // ==>  u.i = x as x is int
u = (union foo) y  // ==>  u.d = y as y is double

 


 

/* By default constant (01234567....) are considered signed integer. */

 


 

/* Casting to UNION with incompatible type is compiler error. */

union foo { unsigned int i; double d; };

union foo bar = (union foo)2;

/* [Error] cast to union type from type not present in union */

/*
Reason: By default 2 (constant) is considered signed integer. union foo doesn't contain any signed int member 
variable. The compiler doesn't to find suitable member to assign value to it. so it throws error.

in order to remove error we can cast constant 2 to unsigned int as:
*/

union foo bar = (union foo)(unsigned int)2;

 


 

/*
if you initialize at least one of the members, the rest of the members will get set to zero (initialized as 
if they had static storage duration).
*/

 


 

typedef struct{
	char x;
	static int y;
}point;

/*
[Error] expected specifier-qualifier-list before 'static'

Can't declare static member inside struct in C (You can have a static member in a C++ structure.) because C 
is not Object Oriented where Objects share member (functions and static variables). I C objects are independent 
of each other.
*/

 


 

/*
Initializing array of structures:
*/
typedef struct{
	char x;
	int y;
}point;

point * a[] = {
	{'a', 2},
	{'b', 1},
	{'c', 5}
};

 


 

/*
What are qualified and un-qualified types in c language?
*/

/*
In the C, C++, and D programming languages, a type qualifier is a keyword that is applied to a type, resulting 
in a qualified type. For example, const int is a qualified type representing a constant integer, while int is the 
corresponding unqualified type, simply an integer.
*/

/*
There are two types of qualifiers available in C language. They are,
1. const
2. volatile
*/

 


 

/*
Avoiding compiler warning for unsed values/parameters.
==> cast it to void to tell the compiler that its okay to ignore the parameter at this moment.
e.g.
*/

int ftn (void) {
.
return xyz;
}

int main () {
    (void) ftn();  //suppress compiler warning
}

/* similarly: */
void ftn (int *xyz) {
    (void)xyz;	// again suppress warning
}

 


 

/*
  Q: Why static and global variable can't be initialized with varialbe?
*/
void main () {
  	int x = 10;
	static int y = x;
}

/*
Error: initializer element is not a constant
*/

/*
This is because the variables are initialized at run-time. ie. memory location depends on current stack pointer 
(especially in interrupt based system). At run time variables are assigned an address  (relative) and value is 
loaded in it. On the other hand static and global variables must have an address assign to them on compile time 
and these variables are initialized before main() by startup (crt0) code. so before main no variable
exists in memory by this time so initialization can't be made at run-time with variable name.
*/

 


 

/*
what will be the output of the following?
*/
int i=5;
printf("%d %d %d %d %d %d",i++,i--,++i,--i,i);

/*
The output is compiler dependent as none of the C standards specify in which order the function parameters should 
be evaluated. so it is left to compiler implementer. so before we can answer this question, we must know the 
sequence point of compiler function evaluational i.e. right or left etc.
*/

 


 

/*
Accessing Linker script symbols:

compiler uses symbol tables to store debug/linker symbols. The table can be thought as:

 _______________________________________________
|          |                |
|  SYMBOL  |    ADDRESS     |
|          |                |
|-----------------------------------------------|
| SYMBOL-1 |    ADDRESS-1   |
| SYMBOL-2 |    ADDRESS-1   |
| SYMBOL-3 |    ADDRESS-1   |
|          |                |
.          .                .
.          .                .
.          .                .
| SYMBOL-N |   ADDRESS-N    |
|___________________________|___________________|

when you define a global variable e.g.
*/

int myVar  = 5;

/*
what compiler does is make an entry in the symbol table for myVar and its address in symbol table
and store value 5 in myVar address.

when you use the address operator with symbol like:
*/

int *ptr = &myVar;

/*
The compiler/linker looks for the symbol myVar in the symbol table, gets the associated address
from the address column and store it in the address pointed by ptr.
*/

/*
Symbol in linker script:
Symbols in linker script are treated a bit differently. there is no value associated with symbols
in linker script. rather the value is treated as an address. e.g.
__SECTION_X_START = 12345

instead of storing the value 12345 into the address pointed by __SECTION_X_START, it makes an entry
in the symbol table for __SECTION_X_START  and place 12345 in address column. Now in order to access
__SECTION_X_START value, you need to use the &amp; sign. e.g.
*/

extern int __SECTION_X_START;

printf ("symbol value is: %d", &amp;__SECTION_X_START );  // prints: symbol value is: 12345

 


 

/*
Integer promotion: 

consider the following example:
*/

uint8_t val = 0x5a;

/*
what will be the result of following expression when the underlaying machine is 32-bits.
*/

(~val) >> 4;

/*
expected: 0xa  (WRONGE..!!!)

why?

the actual result will be: 0x0FFFF,FFa
because  of integer promotion:first the integer will be promoted to underlying machine unsigned int; 

i.e. val: 0x0000005a
(~val) = 0xFFFFFFa5
(~val)>>4 = 0x0FFFFFFa
*/

 


 

/*
The expression in sizeof operator is not evaluated:
sizeof(i = 420)
will give the size of i but the i will not contain 420;
*/

 


 

/*
Why we don't need any prototype for main function?

The answer is hidden in question why we need prototype? Generally prototypes are needed to tell the compiler
what parameters the function is taking and what data type the function returns. For main function the C
standard specifies only two formats i.e.
*/

1. int main ()
2. int main (int argc, char * argv[])

/*
as the function prototype are known at advance (as compiler implements C standard) that's why we don't need
any function prototype for main to tell the compiler what arguments will the main function take and what will
be the return type of the function.
*/

 


 

/*
which one is correct?
*/

float x = 2.0
//or 
float x  = 2.0f

/*
Technically both are correct but the 2.0 is treated as "double" which is implicitly converted to float by the 
compiler before assigning it to x. in second case we are explicitly telling the compiler that 2.0 is float 
type not double.

So 2.0f is correct notation.
*/

 


 

/*
if you do not like the way compiler numbers the lines in the file, you can restart the line numbering with:
*/

#line 2000

/*
Sneak one of these into a colleague's code just before he starts compiling and watch the fun as all of the 
syntax errors are reported on the wrong line.
*/

 


 

/*
Function Prototype vs declaration 

It is never required to declare a prototype for a function in C, neither in "old" C (including C89/90) nor in 
new C (C99). However, there's a significant difference between C89/90 and C99 with regard to function declarations.

In C89/90 it was not necessary to declare a function at all. If the function is not declared at the point of the 
call, the compiler "guesses" (infers) the declaration implicitly from the types of the arguments passed in the 
call and assumes that the return type is int.

For example
*/

int main() {
  int i = foo(5); 
  /* No declaration for `foo`, no prototype for `foo`.
     Will work in C89/90. Assumes `int foo(int)` */

  return 0;
}

int foo(int i) {
  return i;
}

/*
In C99 every function that you call must be declared before point of the call. However, it is still not necessary 
to declare it with a prototype specifically. A non-prototype declaration will work as well. This means that in 
C99 the "implicit int" rule no longer works (for inferred function return types, in this case), but parameter 
types can still be guessed from the argument types if function is declared without a prototype.

The previous example will not compile in C99, since foo is not declared at the point of the call. Yet, 
you can add a non-prototype declaration
*/

int foo(); /* Declares `foo`, but still no prototype */

int main() {
  int i = foo(5); 
  /* No prototype for `foo`, although return type is known. 
     Will work in C99. Assumes `int foo(int)` */

  return 0;
}

/*
...
and end up with valid C99 code.

Nevertheless, it is always a good practice to declare a prototype for the function before you call it.


An additional note: I said above that it is never required to declare a function prototype. In fact, for some 
functions it is a requirement. In order to properly call a variadic function in C (printf for example) the function
must be declared with a prototype before the point of the call. Otherwise, the behavior is undefined. This 
applies to both C89/90 and C99.
*/

 


 

/*
WRONGE... Never do this.
*/

@file1.c
int myarray[5];

@file2.c
extern int *myarray;