SlideShare a Scribd company logo
1 of 95
Download to read offline
Prepared by: Mohamed AbdAllah
Embedded C-Programming
Lecture 2
1
Agenda
 Preprocessor directives (continue).
 Data types (Primitive, derived, user defined).
 Qualifiers (Size, Sign and volatile modifiers and Storage classes).
 Scope and lifetime.
 Makefile introduction.
 Task 2.
2
Agenda
3
Preprocessor directives (continue)
4
 Examples on preprocessor directives (continue):
• Function-like Macro:
#define MAX(a,b) ((a)>(b)) ? (a):(b))
Define macro to be used like a function call, so typing:
int maximum_num = MAX(2,7);
will be replaced with:
int maximum_num = ((2)>(7)) ? (2):(7));
Which will make maximum_num value be 7
5
Preprocessor directives (continue)
 Examples on preprocessor directives (continue):
#define OUTPUT 1
#define LOGIC_HIGH 1
#define LED_INIT(PORT,PIN)
portInit(PORT,PIN,OUTPUT);
portState(PORT,PIN,LOGIC_HIGH)
Define macro to be used like a function call, so typing:
LED_INIT(‘A’,3);
will be the same as typing:
portInit(‘A’,3,OUTPUT);
portState(‘A’,3,LOGIC_HIGH);
Note: Function-like Macro is like normal macro, it is just text replacement.
6
Preprocessor directives (continue)
 Pros and Cons of using Function-like Macro
• Function-like macro usage is just copy and paste, so no function call
actually occurs which makes it faster than function call.
• It is more difficult to debug in function-like macro code than normal
function code.
• Macros are error-prone because they rely on textual substitution:
#define square(a) a*a
/* works fine when used with an integer */
square(5); /* --> 5*5 --> 25 */
/* but does very strange things when used with expressions */
square(1+2); /* --> 1+2*1+2 --> 1+2+2 --> 5 */
square(x++); /* --> x++*x++ --> increments x twice */
7
Preprocessor directives (continue)
 Pros and Cons of using Function-like Macro
Using parentheses around all your variables inside macro will help in first
problem but not the second:
#define square(a) ((a)*(a))
square(1+2); /* --> ((1+2)*(1+2)) --> 3*3 --> 9 */
square(x++);/*((x++)*(x++))-->still increments x twice*/
• Macros do not perform type-checking:
#define MAX(A,B) (((A)>(B)) ? (A) : (B))
Then doing the following will not produce any error or warning:
printf("%dn", MAX("abc","def"));
But if the same was done with usal functions then the compiler will
generate warning during compilation.
8
Preprocessor directives (continue)
 Examples on preprocessor directives (continue):
• Stringification:
#define LED_INIT(PORT,PIN)
printf("Initializing PORT: "#PORT" n");
portInit(PORT,PIN,OUTPUT);
portState(PORT,PIN,LOGIC_HIGH)
When we want to convert a macro argument into a string constant.
So typing:
LED_INIT(‘A’,3);
will be the same as typing:
printf("Initializing PORT: A n");
portInit(‘A’,3,OUTPUT);
portState(‘A’,3,LOGIC_HIGH);
9
Preprocessor directives (continue)
 Examples on preprocessor directives (continue):
• Concatenation:
It is used to merge two tokens into one while expanding macros. This
is called token pasting or token concatenation.
Suppose you have a function with 3 different implementations:
portInit_implementation1(void);
portInit_implementation2(void);
portInit_implementation3(void);
Then you can define:
#define PORT_INIT(NUM)
portInit_implementation ## NUM ()
Then to choose which function of the 3 to call using only PORT_INIT:
PORT_INIT(2);
it is the same as typing:
portInit_implementation2(); 10
Preprocessor directives (continue)
Data types
11
12
Data types
 Primitive Data Types
• The primitive data types in c language are the inbuilt data types
provided by the c language itself. Thus, all c compilers provide support
for these data types.
• The following primitive data types in c are available:
 Integer Data Type, int: Integer data type is used to declare a
variable that can store numbers without a decimal. The keyword
used to declare a variable of integer type is “int”. Thus, to declare
integer data type following syntax should be followed:
int variable_name;
 Float data Type, float: Float data type declares a variable that can
store numbers containing a decimal number:
float variable_name;
13
Data types
 Primitive Data Types
 Double Data Type, double: Double data type also declares variable
that can store floating point numbers but gives precision double
than that provided by float data type. Thus, double data type are
also referred to as double precision data type:
double variable_name;
 Character Data Type, char: Character data type declares a variable
that can store a character constant. Thus, the variables declared as
char data type can only store one single character:
char variable_name;
 Void Data Type, void: Unlike other primitive data types in c, void
data type does not create any variable but returns an empty set of
values. Thus, we can say that it stores null:
void myFunc(); /* Function returns void data type */
14
Data types
 Derived Data Types
• A derived data type is a complex classification of a new data type that is
made up of simpler primitive data type. Derived data types have
advanced properties and uses far beyond those of the basic primitive
data types that operate as their essential building blocks.
• The following are examples for derived data types:
 Array: a kind of data structure that can store a fixed-size sequential
collection of elements of the same type. So instead of typing:
int var1, var2, var3, var4;
We can simply make them in array of 4 integers:
int Arr[4]; /* Uninitialized */
OR
int Arr[4] = {3,2,4,6}; /* Initialized */
Array consists of contiguous memory locations. The lowest index
Arr[0] corresponds to the first element and the highest index Arr[3]
to the last element. 15
Data types
 Derived Data Types (Array continue)
Array can be given value at declaration (Initialized array) or can have
no initial values at declaration.
Array should be fixed size, and size should equal number of
initialization elements:
int Arr[4]; /* Valid*/
int Arr[] = {3,2,4,6}; /* Valid, compiler will put size
= 4 as it is initialized */
int Arr[]; /* Invalid, compiler error */
int Arr[2] = {5,6,7,8}; /* Invalid, compiler error */
Accessing array is through array name and element index:
Arr[2] = 10; /* Change third element */
Exceeding array limits:
int Arr[10]; /* Declare array of 10 integers*/
Arr[15] = 10; /* Will not produce compilation error,
but at runtime it may cause a lot of problems (Data corruption,
program termination, …) */ 16
Data types
 Derived Data Types (Array continue)
String doesn’t exist as a primitive data type in C language, but arrays
can be used to represent string in an array of characters:
char Arr[6] = ‚Hello‛;
Note that array size is number of string characters + 1, this extra
character is used to store the NULL ‘0’ terminator which marks the
end of string, so the following will lead to same result:
char Arr[6] = {‘H’,’e’,’l’,’l’,’o’,’0’};
This NULL terminator is used to know where string ends, for example
when required to print the string:
printf(‚%s‛, Arr) /* Will print Hello*/
Or by doing:
int i = 0;
while(Arr[i] != ‘0’)
printf(‚%c‛, Arr[i++]); /* Will print Hello*/
17
Data types
 Derived Data Types (Array continue)
Till now this is called 1-D (1 dimensional) array.
In memory it looks like that:
18
Data types
Arr[0]
Arr[1]
Arr[2]
Arr[3]
 Derived Data Types (Array continue)
C language also provides a multi-dimensional array, for example we
can create a 2-D array:
int Arr[3][4];
Which can be considered as a table with 3 rows and 4 columns:
19
Data types
column 0 column 1 column 2 column 3
row 0 Arr[0][0] Arr[0][1] Arr[0][2] Arr[0][3]
row 1 Arr[1][0] Arr[1][1] Arr[1][2] Arr[1][3]
row 2 Arr[2][0] Arr[2][1] Arr[2][2] Arr[2][3]
Generally we can any number of dimensions:
int Arr[size1][size2]………..[sizen];
 Derived Data Types (Array continue)
2-D array initialization:
int Arr[3][4] = {
{1,22,13,40}, /* row 0 */
{7,4,45,7}, /* row 1 */
{23,34,83,47} /* row 2 */
};
It can be also initialized like that, but this is not recommended for
readability:
int Arr[3][4] = {1,22,13,40,7,4,45,7,23,34,83,47};
20
Data types
 Derived Data Types
 Function: A function type describes a function with specified
return type. A function type is characterized by its return type and
the number and types of its parameters.
A function type is said to be derived from its return type, and if its
return type is int , the function type is sometimes called function
returning int.
/* Function that returns integer, and takes 2 parameters
first is integer and second is character*/
int myFunc(int x, char y);
This is called function declaration, or function signature.
21
Data types
 Derived Data Types
 Pointers: A pointer is a variable whose value is the address of
another variable, i.e., direct address of the memory location:
int Var1 = 10; /* Var1 is integer contains value 10 */
int *ptr = &Var1; /* ptr is pointer to integer, its
value is the address of Var1 in
memory*/
22
Data types
Memory
Var1 = 10 0xFE00
Ptr = 0xFE00 0xFF04
 Derived Data Types (Pointers continue)
We can make the pointer points to another variable during runtime:
int Var1 = 10, Var2 = 30;
int *ptr = NULL; /* NULL Pointer points to nothing */
ptr = &Var1; /* Pointer now holds Var1 address */
*ptr = 20; /* Change Var1 value through pointer */
ptr = &Var2; /* Pointer now holds Var2 address */
*ptr = 50; /* Var2 will change to be 50 */
23
Data types
 Derived Data Types (Pointers continue)
Pointer size: Pointer size depends on a lot of factors (hardware,
operating system, compiler, etc.), and not all pointer types on the
same platform may have the same size.
For example, there are embedded processors that use a Harvard
architecture, where code and data are in separate memory areas, and
each may have a different address bus size (e.g., 8 bits for data, 16 bits
for code). This means that object pointers (int *, char *, double *) may
be 8 bits wide, but function pointers (int (*)()) may be 16 bits wide.
So on 32-bits address bus controller:
char *ptr;
printf(‚%d‛, sizeof(ptr)); /* Print 4 bytes */
24
Data types
 Derived Data Types (Pointers continue)
Pointer arithmetic: A pointer in c is an address, which is a numeric
value. Therefore, you can perform arithmetic operations on a pointer
just as you can on a numeric value but the result is different than
normal variables. There are four arithmetic operators that can be
used on pointers: ++, --, +, and - .
When we type:
long int Var1 = 10;
long int *ptr = &Var1;
ptr ++;
If Var1 address is for example 1000, then pointer value at the start is
the same as Var1 address which is 1000.
After ptr++ the value of ptr will become 1004, which means it is
incremented by 4 not just 1.
Pointer increment by 1 will increment pointer value by the size of the
variable it points at which is 4 bytes in our case. 25
Data types
 Derived Data Types (Pointers continue)
Another example:
long int Var1 = 10;
long int *ptr = &Var1;
ptr += 3;
If Var1 address is for example 1000, then pointer value at the start is
the same as Var1 address which is 1000.
Adding 3 to ptr will make ptr value becomes 1012, which means it is
incremented by 12 (3 * 4 bytes = 12).
The same for other increment and decrement operations.
26
Data types
 Derived Data Types (Pointers continue)
Pointer can point to any data type, for example pointer to array:
long int Arr[5] = {10,20,30,40,50};
long int *ptr = &Arr[0];
This will make ptr points at the first element in the array so:
printf(‚%d‛, *ptr); /* Will print 10 */
printf(‚%d‛, *(ptr+1)); /* Will print 20*/
printf(‚%d‛, *(ptr+2)); /* Will print 30*/
*(ptr+4) = 0; /*Will change last element in Arr to 0*/
Pointer can also be used like array with index:
printf(‚%d‛, ptr[2]); /* Will print 30 */
ptr[4] = 3; /*Will change last element in Arr to 3*/
27
Data types
 Derived Data Types (Pointers continue)
Pointer can be used to represent string like arrays used:
char *ptr = ‚Hello‛;
printf(‚%s‛, ptr); /* Will print Hello */
This is the same as typing:
char ptr[] = ‚Hello‛;
Note: Array name is itself a pointer to the first element in the array, but it is a
constant pointer so Arr value can’t be changed by any means:
char Arr[6] = ‚Hello‛;
Arr++; /* Compilation error */
28
Data types
 Derived Data Types (Pointers continue)
We can create an array of pointers:
long Var1 = 1, Var2 = 2, Var3 = 3;
long int *ptr[3] = {&Var1, &Var2, &Var3};
/* Now each element in ptr array is a pointer to variable */
printf(‚%d‛, *ptr[0]); /* Will print 1*/
printf(‚%d‛, *ptr[1]); /* Will print 2*/
printf(‚%d‛, *ptr[2]); /* Will print 3*/
29
Data types
 Derived Data Types (Pointers continue)
We can have a pointer to pointer, which means that a pointer 2 holds
the address of pointer 1, and pointer 1 points to any variable:
long Var1 = 1;
long int *ptr1 = &Var1; /* ptr1 points to Var1 */
long int **ptr2 = &ptr1; /* ptr2 points to ptr1 */
30
Data types
*ptr1 = 10; /* Will change Var1 value to 10 */
**ptr2 = 20; /* Will change Var1 value to 20 */
*ptr2 = NULL; /* Will change value of ptr1 to NULL */
Var1 = 1
Address
0xFF00
ptr1 = 0xFF00
Address
0xFFE4ptr2 = 0xFFE4
Address
0xFFF8
Var1 = 20
Address
0xFF00
ptr1 = NULL
Address
0xFFE4ptr2 = 0xFFE4
Address
0xFFF8
 Derived Data Types (Pointers continue)
We can make a pointer to function: A function pointer is a variable
that stores the address of a function that can later be called through
that function pointer.
int myFunc(char myChar)
{
printf(‚Character is %c‛, myChar);
return 0;
}
/* inside any code */
int (*ptr)(char) = myFunc;
/* Now ptr holds the address of function myFunc */
ptr(‘A’); /* Will call myFunc which will print A*/
(*ptr)(‘A’); /* The same as previous line*/
31
Data types
 Derived Data Types (Pointers continue)
Pointers examples: what is the difference between all of this?
int a;
int *a;
int **a;
int a[10];
int *a[10];
int (*a)[10];
int (*a)(int);
int (*a[10])(int);
32
Data types
 Derived Data Types (Pointers continue)
Pointers examples:
int a; /* An integer */
int *a; /* A pointer to an integer */
int **a; /* A pointer to a pointer to an integer */
int a[10]; /* An array of 10 integers */
int *a[10]; /* An array of 10 pointers to integers */
int (*a)[10]; /* A pointer to an array of 10 integers */
int (*a)(int); /* A pointer to a function a that takes an
integer argument and returns an integer */
int (*a[10])(int); /* An array of 10 pointers to
functions that take an integer argument
and return an integer */
33
Data types
 User Defined Data Types
Sometimes, the basic set of data types defined in the C language such
as int, float etc. may be insufficient for your application. In
circumstances such as these, you can create your own data types
which are based on the standard ones.
 Structure: a kind of data structure that can store a collection of
elements that are not of the same type. For example:
struct carInfo {
int speed;
float batteryLevel;
double kilometers;
char bodyTemperature;
};
This is called structure carInfo data type declaration, but till now
there is no variable of that type exists.
34
Data types
 User Defined Data Types (Structure continue)
To declare a variable of type carInfo:
struct carInfo myCar; /* Uninitialized */
OR
struct carInfo myCar = {0, 0, 0, 0}; /*Initialized*/
To edit any value of variable structure members:
myCar.speed = readCarSpeed();
myCar.batteryLevel = readBatteryLevel();
myCar.kilometers = readCarKilometers();
myCar.bodyTemperature = readBodyTemperature();
35
Data types
 User Defined Data Types (Structure continue)
We can define a pointer to structure:
struct carInfo *ptr = &myCar; /*ptr points to myCar*/
Editing structure members through pointer is achieved through arrow
operator ->
ptr->speed = readCarSpeed();
36
Data types
 User Defined Data Types
 Union: A union is a special data type available in C that allows to
store different data types in the same memory location. You can
define a union with many members, but only one member can
contain a valid value at any given time. Unions provide an efficient
way of using the same memory location for multiple-purpose:
union U_data {
int Var1;
double Var2;
char Var3;
};
To declare a variable of type U_data :
union U_data test; /* Uninitialized */
OR
union U_data test = {0}; /*Initialized*/
37
Data types
 User Defined Data Types (Union continue)
Union members share the same memory location, so editing any
member’s value will corrupt other members’ values:
test.Var1 = 32; /* all other members are now 32*/
test.Var2 = 10;/* first 2 bytes of the union
memory contains value 10, other
2 bytes are not changed*/
Size of Union variable test is the size of the biggest union member
(double in our example).
Using union saves memory, but a big caution should be taken to track
which member contains valid data.
38
Data types
 User Defined Data Types
 Enum: An enumeration is a user-defined data type consists of
integral constants and each integral constant is give a name:
enum week {sunday, monday, tuesday, wednesday, thursday,
friday, saturday};
First element in enum by default takes value 0 if not initialized
explicitly, so sunday will have value 0, monday will have value 1 and so
on.
Usage:
enum week today; /*Declare variable of type enum week*/
today = Wednesday; /* today value now is 3*/
39
Data types
 User Defined Data Types (Enum continue)
enum members can be initialized with default values:
enum week {sunday=5,monday,tuesday,Wednesday=9,thursday,
friday, saturday};
Now sunday will have value 5, monday 6, tuesday 7, but wednesday
will be 9 not 8, then thursday 10 and so on.
Note: Multiple members can have the same value, but member name
can’t exist twice.
We can add boolean data type to C language using enum:
enum boolean{ false, true};
enum boolean check; /* Now we can use check as boolean */
40
Data types
 User Defined Data Types
 typedef: We can define any data type we want from another data
type using typdef keyword:
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned long uint32;
typedef unsigned long long uint64;
Now we can use the new defined data types:
uint8 Var1; /*Var1 is unsigned char*/
41
Data types
 User Defined Data Types (typedef continue)
typedef with structure:
typedef struct carInfo {
unsigned long speed;
unsigned short batteryLevel;
unsigned long kilometers;
unsigned char bodyTemperature;
} Car_Type;
Now instead of typing:
struct carInfo myCar;
We can type:
Car_Type myCar;
42
Data types
 User Defined Data Types (typedef continue)
We can simulate the behavior of typedef using #define like that:
#define uint8 unsigned char
uint8 Var1, Var2;/*Var1 and Var2 are now unsigned char*/
But the problem arises when trying something like that:
typedef unsigned char* u8_ptr_Type;
#define u8_ptr_Define unsigned char*
u8_ptr_Type ptr1, ptr2; /* Both will be pointers */
u8_ptr_Define ptr3, ptr4;
It is expected that both ptr3 and ptr4 are of type pointers to unsigned
char, but because #define is just text replacement then what really
happens is that previous line is replaced with:
unsigned char* ptr3, ptr4;
Which will make ptr3 successfully a pointer, but ptr4 will be normal
variable.
43
Data types
 Declaration vs. Definition
Declaration: A declaration tells the compiler the type of a variable,
object or function, but doesn’t allocates memory for it or know all
function details.
extern uint8 Var1; /* Variable extern */
void myFunc(uint8 Var2); /* Function prototype */
This is particularly useful if you are working with multiple source files,
and you need to use a function or variable in multiple files. You don't
want to put the body of the function or same variable in multiple files
statically, but you do need to provide a declaration for it.
Then in only one file you can put the definition.
44
Data types
 Declaration vs. Definition
Definition: A definition allocates memory for a variable or object and
is the implementation of a function.
uint8 Var1 = 10;
void myFunc(uint8 Var2) /* Function Definition*/
{
printf(‚myFunc definitionn‛);
}
Multiple declarations are allowed, but only one definition.
45
Data types
 Overflow vs. Underflow
Overflow: It is the condition that occurs when a calculation produces
a result that is greater in magnitude than the maximum value that a
given register or storage location can store or represent.
Unsigned overflow:
unsigned char Var1 = 255;
Var1++; /* Overflow */
printf(‚%d‛, Var1); /* Prints Zero */
Signed overflow:
signed char Var2 = 127;
Var2++; /* Overflow */
printf(‚%d‛, Var2); /* Prints -128*/
46
Data types
 Overflow vs. Underflow
Underflow: It is the condition that occurs when a calculation produces
a result that is smaller than the minimum value that a can be stored.
Unsigned underflow:
unsigned char Var1 = 0;
Var1 -= 8; /* Underflow */
printf(‚%d‛, Var1); /* Prints 248*/
Signed underflow:
signed char Var2 = -128;
Var2 -= 3; /* Underflow */
printf(‚%d‛, Var1); /* Prints 125*/
47
Data types
 Type Casting
Type casting is a way to convert a variable from one data type to
another data type. For example, if you want to store a 'long' value into
a simple integer then you can type cast 'long' to 'int'.
Explicit casting: You can convert the values from one type to another
explicitly using the cast operator as follows:
(type_name) expression
Example:
int Var1 = 8, Var2 = 20;
float Var3 = (float) Var2 / Var1;
Implicit casting: Implicit casting doesn't require a casting operator.
This casting is normally used when converting data from smaller
integral types to larger or derived types to the base type:
Var3 = Var2; /* Var2 value is implicitly converted to
float and put inside Var3*/
48
Data types
Data Type Qualifiers
49
 Data Type Qualifiers
• Apart from the mentioned primitive data types, there are certain data
type qualifiers that can be applied to them in order to alter their range
and storage space and other properties to fit in various situations as per
the requirement.
• The data type qualifiers available in c are:
 Size modifier: affects size (number of bytes):
short int variable_name; /* 2 bytes integer */
long int variable_name; /* 4 bytes integer */
 Sign modifier: affects values range:
signed int variable_name; /* can have negative range */
unsigned int variable_name; /*can’t have negative range*/
 Constant modifier: affects ability to change it during runtime:
const char Var = ‘A’; /* can’t change at runtime */
50
Data Type Qualifiers
 Primitive Data Types Summary with size and sign modifiers
51
Data type Size Value range
char 1 -128 to 127 or 0 to 255
unsigned char 1 0 to 255
signed char 1 -128 to 127
int 2 or 4 -32,768 to 32,767 or
-2,147,483,648 to
2,147,483,647
unsigned int 2 or 4 0 to 65,535 or
0 to 4,294,967,295
short 2 -32,768 to 32,767
unsigned short 2 0 to 65,535
long 4 -2,147,483,648 to
2,147,483,647
unsigned long 4 0 to 4,294,967,295
Data Type Qualifiers
 Primitive Data Types Summary with size and sign modifiers
52
Data type Size Value range Precision
float 4 1.2E-38 to
3.4E+38
6 decimal places
double 8 2.3E-308 to
1.7E+308
15 decimal
places
long double 10 3.4E-4932 to
1.1E+4932
19 decimal
places
Data Type Qualifiers
 Data Type Qualifiers
It should be noted that the size and sign modifiers cannot be applied to
float and can only be applied to integer and character data types.
 Volatile modifier: tells the compiler that this variable can change
outside of the code control (ex. HW Register value):
volatile char Var = 10;
if (Var == 10)
{
/* Any code*/
/* If variable was not declared volatile, the compiler
may optimize this part by considering the condition
always True and remove the if condition check ! */
}
When a variable is declared volatile, any reference for that variable makes
the compiler reload its value from RAM again to make sure it is the last
updated version of that variable. 53
Data Type Qualifiers
 Data Type Qualifiers
 Storage classes: A storage class defines the scope (visibility) and
life-time of variables and/or functions within a C Program.
o auto: The auto storage class is the default storage class for all
local variables.
int variable_name = 20;
o register: The register storage class is used to define local
variables that should be stored in a register instead of RAM.
This means that the variable has a maximum size equal to the
register size and can't have the unary '&' operator applied to it
(as it does not have a memory location).
/* Compiler will try to put this variable inside
processor registers */
register int variable_name = 10;
54
Data Type Qualifiers
 Data Type Qualifiers
 Storage classes:
o static: The static storage class instructs the compiler to keep a
local variable in existence during the life-time of the program
instead of creating and destroying it each time it comes into
and goes out of scope. Therefore, making local variables static
allows them to maintain their values between function calls.
The static modifier may also be applied to global variables or
functions. When this is done, it causes that variable or function’s
scope to be restricted to the file in which it is declared.
o extern: The extern storage class is used to give a reference of
a global variable or function that is visible to ALL the program
files. When you use 'extern', the variable cannot be initialized
and function can’t have a body however, it points to variable
or function name that has been previously defined in another
file.
55
Data Type Qualifiers
 Data Type Qualifiers
 Storage classes:
56
File1.c
static int variable_1 = 10;
int variable_2 = 20;
File2.c
static int variable_1 = 50;
extern int variable_2;
/* Then inside any part of code */
printf(‚variable_1=%d, variable_2=%d‛, variable_1, variable_2);
/* It will print variable_1=50, variable_2=20 */
Data Type Qualifiers
Scope and Lifetime
57
 Scope
58
Scope and Lifetime
Local scope
File scope
Global scope
 Scope
• The area of our program where we can actually access our variable is
the scope of that variable.
 Local scope: visible within function or statement block from point
of declaration until the end of the block.
void myFunc()
{
uint8 Var1 = 10;
{
uint8 Var2 = 11;
printf(‚%d, %d‛, Var1, Var2);
}
printf(‚%d‛, Var2);
}
Var1 is visible inside all myFunc, but Var2 is only visible inside its inner
block { } which is a local inner scope. 59
Scope and Lifetime
 Scope
 File scope: visible within current file only, but its is visible to all
functions inside this file, by using static keyword with variables or
functions.
60
Scope and Lifetime
File1.c
static int Var1 = 50;
void myFunc1()
{
printf(‚%d‛, Var1);
}
void myFunc2()
{
printf(‚%d‛, Var1);
}
File2.c
void myFunc3()
{
printf(‚%d‛, Var1);
}
File3.c
static int Var1 = 20;
/* Same name, but totally
different variable */
 Scope
 Global scope: visible everywhere, it is defined in one file, and all
other files can use it using extern keyword.
61
Scope and Lifetime
File1.c
int Var1 = 50;
void myFunc1()
{
printf(‚%d‛, Var1);
}
void myFunc2()
{
printf(‚%d‛, Var1);
}
File2.c
extern int Var1;
void myFunc3()
{
printf(‚%d‛, Var1);
}
 Lifetime
• Life time of any variable is the time for which the particular variable
outlives in memory during running of the program.
 Automatic: An automatic variable has a lifetime that begins when
program execution enters the function or statement block or
compound and ends when execution leaves the function or block.
Automatic variables are stored in a "function call stack".
void myFunc()
{
uint8 Var1 = 10;
{
uint8 Var2 = 11;
/* Var2 scope and life time ends here */
}
/* Var1 scope and life time ends here */
}
62
Scope and Lifetime
 Lifetime
 Dynamic: The lifetime of a dynamic data begins when memory is
allocated (e.g., by a call to malloc()) and ends when memory is
deallocated (e.g., by a call to free()). Dynamic data are stored in
"the heap".
/* Allocate 1000 bytes in RAM (Heap part) */
uint8 *myData = (uint8*) malloc(1000);
/* Any code */
free(myData); /* Data is deallocated, so its
life time ends here */
63
Scope and Lifetime
 Lifetime
 Static: A static variable is stored in the data segment of the "object
file" of a program. Its lifetime is the entire duration of the
program's execution.
Static variable is initialized only the first time function is entered, and
its value remains in memory between function calls.
void myFunc()
{
static uint8 Var1 = 10;
printf(‚%d‛, Var1);
Var1++;
}
First call to myFunc will print 10, second call 11, third call 12 and so on.
64
Scope and Lifetime
Makefile introduction
65
 What is Make (GNU Make as an example)
• GNU Make is a tool which controls the generation of executables and
other non-source files of a program from the program's source files.
• Make gets its knowledge of how to build your program from a file called
the makefile, which lists each of the non-source files and how to
compute it from other files. When you write a program, you should
write a makefile for it, so that it is possible to use Make to build and
install the program.
66
Makefile introduction
 Capabilities of Make
• Make enables the end user to build and install your package (in case
you provided them with source code) without knowing the details of
how that is done because these details are recorded in the makefile
that you supply.
• Make figures out automatically which files it needs to update, based on
which source files have changed. It also automatically determines the
proper order for updating files, in case one non-source file depends on
another non-source file.
As a result, if you change a few source files and then run Make, it does
not need to recompile all of your program. It updates only those non-
source files that depend directly or indirectly on the source files that you
changed.
• Make is not limited to any particular language. For each non-source file
in the program, the makefile specifies the shell commands to compute
it. These shell commands can run a compiler to produce an object file,
the linker to produce an executable, ar to update a library..etc. 67
Makefile introduction
 makefile structure
• Make searches for a file called makefile without any extension to do its
work.
• Basic building elements of make file are:
 Target: What is the output of current step.
 Dependencies: What should be already available to start making
current target.
 Commands: What should be done to make current target.
All of them are called “Rule”. A rule in the makefile tells Make how to
execute a series of commands in order to build a target file from source
files. It also specifies a list of dependencies of the target file. This list
should include all files (whether source files or other targets) which are
used as inputs to the commands in the rule.
68
Makefile introduction
 makefile structure
• Rule structure:
69
Makefile introduction
• Target name is typed at start of line, then followed by a colon : then
followed by list of all dependencies that should be available to start
executing commands, then on each new line write a new command to
be executed, each command should have a Tab space before it or the
make will not work.
• Dependencies can be on one line, or can be divided on multiple lines:
Target: dependency1 dependency2 ...
commands
...
Target: dependency1 dependency2
dependency3 ...
commands
...
 makefile structure
• Rule example:
70
Makefile introduction
D:newProject>make file.o
file.o: file.c
gcc -c file.c -o file.o
Create any C code file with the name file.c and put it in the same directory
with the makefile.
Then by running Make through command line:
Create a text file with the name makefile without any extension and type
the following inside it:
 The Make utility will search for the file makefile, then it will search
inside it for the required target file.o .
 It will search what are file.o dependencies, it will find that it only
depends on file.c.
 makefile structure
 It will check “is the required dependency file.c available ?”, the Make
file will find it in the same directory.
 After the Make utility finds file.c, it will execute the commands under
file.o target which is here compiling file.c, so the output of this
command will be:
71
Makefile introduction
D:newProject>make file.o
gcc -c file.c -o file.o
 Now you will find in the same directory a file created called file.o which
is the compiled output file of file.c .
 makefile structure
• If the Make didn’t find the required dependency file, it will search if this
dependency is another required target then do it first:
72
Makefile introduction
app.exe: file1.o file2.o
gcc file1.o file2.o -o app.exe
file1.o: file1.c
gcc -c file1.c -o file1.o
file2.o: file2.c
gcc -c file2.c -o file2.o
Create a C code file with the name file1.c which contains the main
function, create another C code file file2.c with any code, and put them in
the same directory with the makefile.
 makefile structure
73
Makefile introduction
Run the Make and the output will be:
D:newProject>make app.exe
gcc -c file1.c -o file1.o
gcc -c file2.c -o file2.o
gcc file1.o file2.o -o app.exe
Now you will find in the same directory a file called app.exe which is the
compilation output.
 makefile structure
• If the Make didn’t find the required dependency file in the directory or
as any other target then it will generate this error and stop:
74
Makefile introduction
D:newProject>make newFile.c
make: *** No rule to make target `newFile.c'. Stop.
• If Tab space doesn’t exist before any command then Make will generate
this error and stop (note that 5 is number of first line containing error):
D:newProject>make app.exe
makefile:5: *** missing separator. Stop.
• When you run Make, you can specify particular targets to update;
otherwise, Make updates the first target listed in the makefile. Of
course, any other target files needed as input for generating these
targets must be updated first.
 makefile structure
• Usually makefile contains 2 targets called all and clean to be used by
any one without knowing the details of our makefile content:
75
Makefile introduction
# all target is usually put as the first target
all: app.exe
clean:
rm file1.o file2.o app.exe
app.exe: file1.o file2.o
gcc file1.o file2.o -o app.exe
file1.o: file1.c
gcc -c file1.c -o file1.o
file2.o: file2.c
gcc -c file2.c -o file2.o
 makefile structure
• So typing all target will output the same result as typing app.exe, and
typing clean target will delete file1.o, file2.o and app.exe .
76
Makefile introduction
D:newProject>make clean
rm file1.o file2.o app.exe
• clean and all targets are called “Phony Targets”. A phony target is one
that is not really the name of a file, rather it is just a name for a recipe
to be executed when you make an explicit request, it may have
dependencies like all target and may not have any dependencies like
clean target.
 Make variables
• A variable begins with a $ and is enclosed within parentheses (...) or
braces {...}. Single character variables do not need the parentheses.
Example:
77
Makefile introduction
CC = gcc
file1.o: file1.c
$(CC) -c file1.c -o file1.o
 Make variables
• Automatic Variables:
Automatic variables are set by make after a rule is matched. They include:
$@: the target filename.
$*: the target filename without the file extension.
$<: the first prerequisite filename.
$^: the filenames of all the prerequisites, separated by spaces, discard
duplicates.
$+: similar to $^, but includes duplicates.
$?: the names of all prerequisites that are newer than the target,
separated by spaces.
78
Makefile introduction
 Make variables
Example 1:
79
Makefile introduction
file1.o: file1.c
$(CC) -c $< -o $@
# It is the same as typing $(CC) -c file1.c -o file1.o
Example 2:
OBJ_FILES = file1.o file2.o
app.exe: $(OBJ_FILES)
$(CC) $^ -o $@
# It is the same as typing:
# $(CC) file1.o file2.o -o app.exe
 Make variables
Example 3:
80
Makefile introduction
OBJ_FILES = file1.o file2.o
LINK_TARGET = app.exe
CLEAN_TARGET = $(LINK_TARGET) $(OBJ_FILES)
all: $(LINK_TARGET)
# It is the same as typing:
# all: app.exe
clean:
rm $(CLEAN_TARGET)
# It is the same as typing:
# clean:
rm file1.o file2.o app.exe
 Make implicit rules
Implicit rules are a set of generalized instructions for doing certain tasks,
where the instructions are provided as default.
For example, an implicit rule can tell Make utility how to construct a .o file
from a .c file without explicitly typing files names.
Example 1:
81
Makefile introduction
%.o: %.c
$(CC) -c $< -o $@
# It means ‚whenever you find a required target with
#any name but with extention .o and there is no
#explicit rule for how to make this target, then
#execute the next commands on this target.
 Make implicit rules
Example 2:
82
Makefile introduction
%.o: %.c
$(CC) -c $< -o $@
file1.o: file1.c
$(CC) -c file1.c -o explicit_file1.o
app.exe: file1.o file2.o file3.o
$(CC) $^ -o $@
# For file2.o and file3.o it will use the implicit
#rule, so their output names will be file2.o and
#file3.o but for file1.o it will find an explicit rule
#for it then it will execute it, so its output name
#will be explicit_file1.o
 Creating project hierarchy
Most of the time the project contains different folders, not just all source
and headers files in the same place, for example if we need to make one
folder for source code files with name “src” and another folder for header
files with name “inc”, then in the makefile we should do the following
(assuming that the makefile is in the same directory as both folders):
83
Makefile introduction
# Tell makefile Where to find source files
vpath %.c ./src
# Header files path
INCLUDE_PATH = ./inc
%.o: %.c
$(CC) -c -I$(INCLUDE_PATH) $< -o $@
# -I$(INCLUDE_PATH) tells the compiler where to find
#header files
 Header files issue
After running make all, if we edited any source file the Make utility will
recompile this file only and targets that depends on it.
But if we changed any header file the make utility will not even notice and
will not make any recompilation for the source code that depends on this
file which we don’t want. This is because we didn’t tell the Make utility any
thing about header files dependencies inside the makefile.
That’s why we should make dependencies generation, which makes the
compiler enters all source files, extract information about what header
files that each source file depends on, generate a corresponding
dependency file for this source file and include this information in our
makefile.
After making these steps, whenever we change a header file, any source
file that depends on this header file will be recompiled and any target that
depends on this source file will be made again.
84
Makefile introduction
 Header files issue (solution)
85
Makefile introduction
# Generate dependencies list
# Dependencies output path
DEPS_PATH = ./dep/
# Source files path
SRC_PATH = ./src/
# Header files path
INCLUDE_PATH = ./inc/
# Get source files names with path
SRC_FILES_ABSOLUTE = $(wildcard $(SRC_PATH)*.c)
# Get source files names without path
SRC_FILES = $(patsubst $(SRC_PATH)%.c,%.c,$(SRC_FILES_ABSOLUTE))
 Header files issue (solution)
86
Makefile introduction
# Make dependencies names the same as sources names but with extension .d
DEPS_FILES = $(patsubst %.c,%.d,$(SRC_FILES))
# Get dependencies files names with their path
DEPS_FILES_ABSOLUTE = $(patsubst %.d,$(DEPS_PATH)%.d,$(DEPS_FILES))
# Rule to make dependencies files
$(DEPS_PATH)%.d : %.c
# Generate dependencies files (Small make file for each c file)
$(CC) -MM -MP -MT$@ -I$(INCLUDE_PATH) $< -o $@
 Header files issue (solution)
87
Makefile introduction
# Include all dependencies make files inside current make to be
#used in #linking target to detect when any header file changes
-include $(DEPS_FILES_ABSOLUTE)
# Add dependencies to our target
app.exe: $(OBJ_FILES) $(DEPS_FILES_ABSOLUTE)
$(CC) $^ -o $@
 Make simple complete example
Create 3 different folders:
• src: contains all your source files.
• inc: contains all your header files.
• dep: empty, will be the output for dependencies files.
Create empty text file with the name makefile without any extension and
put the following inside the file:
88
Makefile introduction
 Make simple complete example
89
Makefile introduction
# Tell makefile Where to find source files
vpath %.c ./src
# Compiler used
CC = gcc
# Dependencies output path
DEPS_PATH = ./dep/
# Source files path
SRC_PATH = ./src/
# Header files path
INCLUDE_PATH = ./inc/
 Make simple complete example
90
Makefile introduction
# What is our target name
LINK_TARGET = app.exe
# Objects used later to be linked to generate our link target
OBJ = main.o
Func1.o
Func2.o
Func3.o
# What will be used at clean target
CLEAN_TARGET = $(LINK_TARGET) $(OBJ)
# Used with > make all
all:$(LINK_TARGET)
echo Bulding done !
 Make simple complete example
91
Makefile introduction
# Used with > make clean
clean:
rm $(CLEAN_TARGET)
echo Cleaning done !
# What will happen when requiring $(LINK_TARGET)
$(LINK_TARGET): $(OBJ) $(DEPS_FILES_ABSOLUTE)
$(CC) $(OBJ) -o $@
echo Linking done !
# What will happening when requiring any target with any file name with
#extension .o
%.o: %.c
$(CC) -c -I$(INCLUDE_PATH) $< -o $@
echo File $< compilation done !
 Make simple complete example
92
Makefile introduction
# Generate dependencies list
# Get source files names with path
SRC_FILES_ABSOLUTE = $(wildcard $(SRC_PATH)*.c)
# Get source files names without path
SRC_FILES = $(patsubst $(SRC_PATH)%.c,%.c,$(SRC_FILES_ABSOLUTE))
# Make dependencies names the same as sources names but with extension .d
DEPS_FILES = $(patsubst %.c,%.d,$(SRC_FILES))
# Get dependencies files names with their path
DEPS_FILES_ABSOLUTE = $(patsubst %.d,$(DEPS_PATH)%.d,$(DEPS_FILES))
 Make simple complete example
93
Makefile introduction
# Rule to make dependencies files
$(DEPS_PATH)%.d : %.c
#Generate dependencies files (Small make file for each c file)
$(CC) -MM -MP -MT$@ -I$(INCLUDE_PATH) $< -o $@
# Include all dependencies files inside current make to be used in
#linking target to detect when any header file changes
-include $(DEPS_FILES_ABSOLUTE)
Task 2
94
Mohamed AbdAllah
Embedded Systems Engineer
mohabdallah8@gmail.com
95

More Related Content

What's hot

What's hot (20)

Embedded C programming session10
Embedded C programming  session10Embedded C programming  session10
Embedded C programming session10
 
Operand and Opcode | Computer Science
Operand and Opcode | Computer ScienceOperand and Opcode | Computer Science
Operand and Opcode | Computer Science
 
Embedded c
Embedded cEmbedded c
Embedded c
 
Verilog hdl
Verilog hdlVerilog hdl
Verilog hdl
 
Pointers in c++
Pointers in c++Pointers in c++
Pointers in c++
 
VHDL- data types
VHDL- data typesVHDL- data types
VHDL- data types
 
Function C programming
Function C programmingFunction C programming
Function C programming
 
Input output accessing
Input output accessingInput output accessing
Input output accessing
 
Verilog tutorial
Verilog tutorialVerilog tutorial
Verilog tutorial
 
Pentium processor
Pentium processorPentium processor
Pentium processor
 
Instruction formats-in-8086
Instruction formats-in-8086Instruction formats-in-8086
Instruction formats-in-8086
 
Interrupts of microprocessor 8085
Interrupts of microprocessor  8085Interrupts of microprocessor  8085
Interrupts of microprocessor 8085
 
INTRODUCTION TO MICROCONTROLLER
INTRODUCTION TO MICROCONTROLLERINTRODUCTION TO MICROCONTROLLER
INTRODUCTION TO MICROCONTROLLER
 
Pointers in c++
Pointers in c++Pointers in c++
Pointers in c++
 
Register introduction
Register introductionRegister introduction
Register introduction
 
Intermediate code generation in Compiler Design
Intermediate code generation in Compiler DesignIntermediate code generation in Compiler Design
Intermediate code generation in Compiler Design
 
5bit field
5bit field5bit field
5bit field
 
Multidimensional array in C
Multidimensional array in CMultidimensional array in C
Multidimensional array in C
 
General Purpose Input Output - Brief Introduction
General Purpose Input Output - Brief IntroductionGeneral Purpose Input Output - Brief Introduction
General Purpose Input Output - Brief Introduction
 
Pin Description Of Intel 80386 DX Microprocessor
Pin Description Of Intel 80386 DX MicroprocessorPin Description Of Intel 80386 DX Microprocessor
Pin Description Of Intel 80386 DX Microprocessor
 

Viewers also liked

Raspberry Pi - Lecture 3 Embedded Communication Protocols
Raspberry Pi - Lecture 3 Embedded Communication ProtocolsRaspberry Pi - Lecture 3 Embedded Communication Protocols
Raspberry Pi - Lecture 3 Embedded Communication ProtocolsMohamed Abdallah
 
Raspberry Pi - Lecture 2 Linux OS
Raspberry Pi - Lecture 2 Linux OSRaspberry Pi - Lecture 2 Linux OS
Raspberry Pi - Lecture 2 Linux OSMohamed Abdallah
 
Raspberry Pi - Lecture 1 Introduction
Raspberry Pi - Lecture 1 IntroductionRaspberry Pi - Lecture 1 Introduction
Raspberry Pi - Lecture 1 IntroductionMohamed Abdallah
 
Raspberry Pi - Lecture 5 Python for Raspberry Pi
Raspberry Pi - Lecture 5 Python for Raspberry PiRaspberry Pi - Lecture 5 Python for Raspberry Pi
Raspberry Pi - Lecture 5 Python for Raspberry PiMohamed Abdallah
 
Raspberry Pi - Lecture 4 Hardware Interfacing Special Cases
Raspberry Pi - Lecture 4 Hardware Interfacing Special CasesRaspberry Pi - Lecture 4 Hardware Interfacing Special Cases
Raspberry Pi - Lecture 4 Hardware Interfacing Special CasesMohamed Abdallah
 
Embedded C programming based on 8051 microcontroller
Embedded C programming based on 8051 microcontrollerEmbedded C programming based on 8051 microcontroller
Embedded C programming based on 8051 microcontrollerGaurav Verma
 
Raspberry Pi - Lecture 6 Working on Raspberry Pi
Raspberry Pi - Lecture 6 Working on Raspberry PiRaspberry Pi - Lecture 6 Working on Raspberry Pi
Raspberry Pi - Lecture 6 Working on Raspberry PiMohamed Abdallah
 
Embedded c c++ programming fundamentals master
Embedded c c++ programming fundamentals masterEmbedded c c++ programming fundamentals master
Embedded c c++ programming fundamentals masterHossam Hassan
 
C Programming For Embedded Systems
C Programming For Embedded SystemsC Programming For Embedded Systems
C Programming For Embedded SystemsGanesh Samarthyam
 
Question paper with solution the 8051 microcontroller based embedded systems...
Question paper with solution  the 8051 microcontroller based embedded systems...Question paper with solution  the 8051 microcontroller based embedded systems...
Question paper with solution the 8051 microcontroller based embedded systems...manishpatel_79
 
Basics of C programming
Basics of C programmingBasics of C programming
Basics of C programmingavikdhupar
 
Responding to the Department of Education Program Review
Responding to the Department of Education Program ReviewResponding to the Department of Education Program Review
Responding to the Department of Education Program ReviewDennis Cariello
 

Viewers also liked (20)

Raspberry Pi - Lecture 3 Embedded Communication Protocols
Raspberry Pi - Lecture 3 Embedded Communication ProtocolsRaspberry Pi - Lecture 3 Embedded Communication Protocols
Raspberry Pi - Lecture 3 Embedded Communication Protocols
 
Raspberry Pi - Lecture 2 Linux OS
Raspberry Pi - Lecture 2 Linux OSRaspberry Pi - Lecture 2 Linux OS
Raspberry Pi - Lecture 2 Linux OS
 
Raspberry Pi - Lecture 1 Introduction
Raspberry Pi - Lecture 1 IntroductionRaspberry Pi - Lecture 1 Introduction
Raspberry Pi - Lecture 1 Introduction
 
Raspberry Pi - Lecture 5 Python for Raspberry Pi
Raspberry Pi - Lecture 5 Python for Raspberry PiRaspberry Pi - Lecture 5 Python for Raspberry Pi
Raspberry Pi - Lecture 5 Python for Raspberry Pi
 
Raspberry Pi - Lecture 4 Hardware Interfacing Special Cases
Raspberry Pi - Lecture 4 Hardware Interfacing Special CasesRaspberry Pi - Lecture 4 Hardware Interfacing Special Cases
Raspberry Pi - Lecture 4 Hardware Interfacing Special Cases
 
Embedded C programming based on 8051 microcontroller
Embedded C programming based on 8051 microcontrollerEmbedded C programming based on 8051 microcontroller
Embedded C programming based on 8051 microcontroller
 
Raspberry Pi - Lecture 6 Working on Raspberry Pi
Raspberry Pi - Lecture 6 Working on Raspberry PiRaspberry Pi - Lecture 6 Working on Raspberry Pi
Raspberry Pi - Lecture 6 Working on Raspberry Pi
 
Embedded c c++ programming fundamentals master
Embedded c c++ programming fundamentals masterEmbedded c c++ programming fundamentals master
Embedded c c++ programming fundamentals master
 
Embedded System Basics
Embedded System BasicsEmbedded System Basics
Embedded System Basics
 
C Programming For Embedded Systems
C Programming For Embedded SystemsC Programming For Embedded Systems
C Programming For Embedded Systems
 
Embedded _c_
Embedded  _c_Embedded  _c_
Embedded _c_
 
Data Structures & Algorithm design using C
Data Structures & Algorithm design using C Data Structures & Algorithm design using C
Data Structures & Algorithm design using C
 
Embedded C - Optimization techniques
Embedded C - Optimization techniquesEmbedded C - Optimization techniques
Embedded C - Optimization techniques
 
Embedded Linux on ARM
Embedded Linux on ARMEmbedded Linux on ARM
Embedded Linux on ARM
 
Embedded C
Embedded CEmbedded C
Embedded C
 
Communication Protocols (UART, SPI,I2C)
Communication Protocols (UART, SPI,I2C)Communication Protocols (UART, SPI,I2C)
Communication Protocols (UART, SPI,I2C)
 
Question paper with solution the 8051 microcontroller based embedded systems...
Question paper with solution  the 8051 microcontroller based embedded systems...Question paper with solution  the 8051 microcontroller based embedded systems...
Question paper with solution the 8051 microcontroller based embedded systems...
 
Linux device drivers
Linux device drivers Linux device drivers
Linux device drivers
 
Basics of C programming
Basics of C programmingBasics of C programming
Basics of C programming
 
Responding to the Department of Education Program Review
Responding to the Department of Education Program ReviewResponding to the Department of Education Program Review
Responding to the Department of Education Program Review
 

Similar to Embedded C - Lecture 2

Similar to Embedded C - Lecture 2 (20)

C programming language tutorial
C programming language tutorial C programming language tutorial
C programming language tutorial
 
C programming day#2.
C programming day#2.C programming day#2.
C programming day#2.
 
Theory1&amp;2
Theory1&amp;2Theory1&amp;2
Theory1&amp;2
 
Chapter1.pptx
Chapter1.pptxChapter1.pptx
Chapter1.pptx
 
Unit 3
Unit 3 Unit 3
Unit 3
 
C
CC
C
 
Introduction to c
Introduction to cIntroduction to c
Introduction to c
 
C programming session 01
C programming session 01C programming session 01
C programming session 01
 
Arrays and strings in c++
Arrays and strings in c++Arrays and strings in c++
Arrays and strings in c++
 
The best every notes on c language is here check it out
The best every notes on c language is here check it outThe best every notes on c language is here check it out
The best every notes on c language is here check it out
 
Esoft Metro Campus - Certificate in c / c++ programming
Esoft Metro Campus - Certificate in c / c++ programmingEsoft Metro Campus - Certificate in c / c++ programming
Esoft Metro Campus - Certificate in c / c++ programming
 
See through C
See through CSee through C
See through C
 
Programming Fundamentals lecture 6
Programming Fundamentals lecture 6Programming Fundamentals lecture 6
Programming Fundamentals lecture 6
 
Chapter 2.datatypes and operators
Chapter 2.datatypes and operatorsChapter 2.datatypes and operators
Chapter 2.datatypes and operators
 
VIT351 Software Development VI Unit2
VIT351 Software Development VI Unit2VIT351 Software Development VI Unit2
VIT351 Software Development VI Unit2
 
C cheat sheet for varsity (extreme edition)
C cheat sheet for varsity (extreme edition)C cheat sheet for varsity (extreme edition)
C cheat sheet for varsity (extreme edition)
 
C programming
C programmingC programming
C programming
 
ch08.ppt
ch08.pptch08.ppt
ch08.ppt
 
C++_notes.pdf
C++_notes.pdfC++_notes.pdf
C++_notes.pdf
 
Unit 3
Unit 3 Unit 3
Unit 3
 

Recently uploaded

Oxy acetylene welding presentation note.
Oxy acetylene welding presentation note.Oxy acetylene welding presentation note.
Oxy acetylene welding presentation note.eptoze12
 
computer application and construction management
computer application and construction managementcomputer application and construction management
computer application and construction managementMariconPadriquez1
 
Study on Air-Water & Water-Water Heat Exchange in a Finned Tube Exchanger
Study on Air-Water & Water-Water Heat Exchange in a Finned Tube ExchangerStudy on Air-Water & Water-Water Heat Exchange in a Finned Tube Exchanger
Study on Air-Water & Water-Water Heat Exchange in a Finned Tube ExchangerAnamika Sarkar
 
Software and Systems Engineering Standards: Verification and Validation of Sy...
Software and Systems Engineering Standards: Verification and Validation of Sy...Software and Systems Engineering Standards: Verification and Validation of Sy...
Software and Systems Engineering Standards: Verification and Validation of Sy...VICTOR MAESTRE RAMIREZ
 
Class 1 | NFPA 72 | Overview Fire Alarm System
Class 1 | NFPA 72 | Overview Fire Alarm SystemClass 1 | NFPA 72 | Overview Fire Alarm System
Class 1 | NFPA 72 | Overview Fire Alarm Systemirfanmechengr
 
Arduino_CSE ece ppt for working and principal of arduino.ppt
Arduino_CSE ece ppt for working and principal of arduino.pptArduino_CSE ece ppt for working and principal of arduino.ppt
Arduino_CSE ece ppt for working and principal of arduino.pptSAURABHKUMAR892774
 
Concrete Mix Design - IS 10262-2019 - .pptx
Concrete Mix Design - IS 10262-2019 - .pptxConcrete Mix Design - IS 10262-2019 - .pptx
Concrete Mix Design - IS 10262-2019 - .pptxKartikeyaDwivedi3
 
Earthing details of Electrical Substation
Earthing details of Electrical SubstationEarthing details of Electrical Substation
Earthing details of Electrical Substationstephanwindworld
 
TechTAC® CFD Report Summary: A Comparison of Two Types of Tubing Anchor Catchers
TechTAC® CFD Report Summary: A Comparison of Two Types of Tubing Anchor CatchersTechTAC® CFD Report Summary: A Comparison of Two Types of Tubing Anchor Catchers
TechTAC® CFD Report Summary: A Comparison of Two Types of Tubing Anchor Catcherssdickerson1
 
lifi-technology with integration of IOT.pptx
lifi-technology with integration of IOT.pptxlifi-technology with integration of IOT.pptx
lifi-technology with integration of IOT.pptxsomshekarkn64
 
US Department of Education FAFSA Week of Action
US Department of Education FAFSA Week of ActionUS Department of Education FAFSA Week of Action
US Department of Education FAFSA Week of ActionMebane Rash
 
Call Us ≽ 8377877756 ≼ Call Girls In Shastri Nagar (Delhi)
Call Us ≽ 8377877756 ≼ Call Girls In Shastri Nagar (Delhi)Call Us ≽ 8377877756 ≼ Call Girls In Shastri Nagar (Delhi)
Call Us ≽ 8377877756 ≼ Call Girls In Shastri Nagar (Delhi)dollysharma2066
 
Correctly Loading Incremental Data at Scale
Correctly Loading Incremental Data at ScaleCorrectly Loading Incremental Data at Scale
Correctly Loading Incremental Data at ScaleAlluxio, Inc.
 
Transport layer issues and challenges - Guide
Transport layer issues and challenges - GuideTransport layer issues and challenges - Guide
Transport layer issues and challenges - GuideGOPINATHS437943
 
Introduction to Machine Learning Unit-3 for II MECH
Introduction to Machine Learning Unit-3 for II MECHIntroduction to Machine Learning Unit-3 for II MECH
Introduction to Machine Learning Unit-3 for II MECHC Sai Kiran
 
complete construction, environmental and economics information of biomass com...
complete construction, environmental and economics information of biomass com...complete construction, environmental and economics information of biomass com...
complete construction, environmental and economics information of biomass com...asadnawaz62
 
Instrumentation, measurement and control of bio process parameters ( Temperat...
Instrumentation, measurement and control of bio process parameters ( Temperat...Instrumentation, measurement and control of bio process parameters ( Temperat...
Instrumentation, measurement and control of bio process parameters ( Temperat...121011101441
 
CCS355 Neural Networks & Deep Learning Unit 1 PDF notes with Question bank .pdf
CCS355 Neural Networks & Deep Learning Unit 1 PDF notes with Question bank .pdfCCS355 Neural Networks & Deep Learning Unit 1 PDF notes with Question bank .pdf
CCS355 Neural Networks & Deep Learning Unit 1 PDF notes with Question bank .pdfAsst.prof M.Gokilavani
 

Recently uploaded (20)

Oxy acetylene welding presentation note.
Oxy acetylene welding presentation note.Oxy acetylene welding presentation note.
Oxy acetylene welding presentation note.
 
computer application and construction management
computer application and construction managementcomputer application and construction management
computer application and construction management
 
Study on Air-Water & Water-Water Heat Exchange in a Finned Tube Exchanger
Study on Air-Water & Water-Water Heat Exchange in a Finned Tube ExchangerStudy on Air-Water & Water-Water Heat Exchange in a Finned Tube Exchanger
Study on Air-Water & Water-Water Heat Exchange in a Finned Tube Exchanger
 
Software and Systems Engineering Standards: Verification and Validation of Sy...
Software and Systems Engineering Standards: Verification and Validation of Sy...Software and Systems Engineering Standards: Verification and Validation of Sy...
Software and Systems Engineering Standards: Verification and Validation of Sy...
 
Class 1 | NFPA 72 | Overview Fire Alarm System
Class 1 | NFPA 72 | Overview Fire Alarm SystemClass 1 | NFPA 72 | Overview Fire Alarm System
Class 1 | NFPA 72 | Overview Fire Alarm System
 
Arduino_CSE ece ppt for working and principal of arduino.ppt
Arduino_CSE ece ppt for working and principal of arduino.pptArduino_CSE ece ppt for working and principal of arduino.ppt
Arduino_CSE ece ppt for working and principal of arduino.ppt
 
Concrete Mix Design - IS 10262-2019 - .pptx
Concrete Mix Design - IS 10262-2019 - .pptxConcrete Mix Design - IS 10262-2019 - .pptx
Concrete Mix Design - IS 10262-2019 - .pptx
 
9953056974 Call Girls In South Ex, Escorts (Delhi) NCR.pdf
9953056974 Call Girls In South Ex, Escorts (Delhi) NCR.pdf9953056974 Call Girls In South Ex, Escorts (Delhi) NCR.pdf
9953056974 Call Girls In South Ex, Escorts (Delhi) NCR.pdf
 
Earthing details of Electrical Substation
Earthing details of Electrical SubstationEarthing details of Electrical Substation
Earthing details of Electrical Substation
 
TechTAC® CFD Report Summary: A Comparison of Two Types of Tubing Anchor Catchers
TechTAC® CFD Report Summary: A Comparison of Two Types of Tubing Anchor CatchersTechTAC® CFD Report Summary: A Comparison of Two Types of Tubing Anchor Catchers
TechTAC® CFD Report Summary: A Comparison of Two Types of Tubing Anchor Catchers
 
lifi-technology with integration of IOT.pptx
lifi-technology with integration of IOT.pptxlifi-technology with integration of IOT.pptx
lifi-technology with integration of IOT.pptx
 
US Department of Education FAFSA Week of Action
US Department of Education FAFSA Week of ActionUS Department of Education FAFSA Week of Action
US Department of Education FAFSA Week of Action
 
young call girls in Rajiv Chowk🔝 9953056974 🔝 Delhi escort Service
young call girls in Rajiv Chowk🔝 9953056974 🔝 Delhi escort Serviceyoung call girls in Rajiv Chowk🔝 9953056974 🔝 Delhi escort Service
young call girls in Rajiv Chowk🔝 9953056974 🔝 Delhi escort Service
 
Call Us ≽ 8377877756 ≼ Call Girls In Shastri Nagar (Delhi)
Call Us ≽ 8377877756 ≼ Call Girls In Shastri Nagar (Delhi)Call Us ≽ 8377877756 ≼ Call Girls In Shastri Nagar (Delhi)
Call Us ≽ 8377877756 ≼ Call Girls In Shastri Nagar (Delhi)
 
Correctly Loading Incremental Data at Scale
Correctly Loading Incremental Data at ScaleCorrectly Loading Incremental Data at Scale
Correctly Loading Incremental Data at Scale
 
Transport layer issues and challenges - Guide
Transport layer issues and challenges - GuideTransport layer issues and challenges - Guide
Transport layer issues and challenges - Guide
 
Introduction to Machine Learning Unit-3 for II MECH
Introduction to Machine Learning Unit-3 for II MECHIntroduction to Machine Learning Unit-3 for II MECH
Introduction to Machine Learning Unit-3 for II MECH
 
complete construction, environmental and economics information of biomass com...
complete construction, environmental and economics information of biomass com...complete construction, environmental and economics information of biomass com...
complete construction, environmental and economics information of biomass com...
 
Instrumentation, measurement and control of bio process parameters ( Temperat...
Instrumentation, measurement and control of bio process parameters ( Temperat...Instrumentation, measurement and control of bio process parameters ( Temperat...
Instrumentation, measurement and control of bio process parameters ( Temperat...
 
CCS355 Neural Networks & Deep Learning Unit 1 PDF notes with Question bank .pdf
CCS355 Neural Networks & Deep Learning Unit 1 PDF notes with Question bank .pdfCCS355 Neural Networks & Deep Learning Unit 1 PDF notes with Question bank .pdf
CCS355 Neural Networks & Deep Learning Unit 1 PDF notes with Question bank .pdf
 

Embedded C - Lecture 2

  • 1. Prepared by: Mohamed AbdAllah Embedded C-Programming Lecture 2 1
  • 2. Agenda  Preprocessor directives (continue).  Data types (Primitive, derived, user defined).  Qualifiers (Size, Sign and volatile modifiers and Storage classes).  Scope and lifetime.  Makefile introduction.  Task 2. 2
  • 5.  Examples on preprocessor directives (continue): • Function-like Macro: #define MAX(a,b) ((a)>(b)) ? (a):(b)) Define macro to be used like a function call, so typing: int maximum_num = MAX(2,7); will be replaced with: int maximum_num = ((2)>(7)) ? (2):(7)); Which will make maximum_num value be 7 5 Preprocessor directives (continue)
  • 6.  Examples on preprocessor directives (continue): #define OUTPUT 1 #define LOGIC_HIGH 1 #define LED_INIT(PORT,PIN) portInit(PORT,PIN,OUTPUT); portState(PORT,PIN,LOGIC_HIGH) Define macro to be used like a function call, so typing: LED_INIT(‘A’,3); will be the same as typing: portInit(‘A’,3,OUTPUT); portState(‘A’,3,LOGIC_HIGH); Note: Function-like Macro is like normal macro, it is just text replacement. 6 Preprocessor directives (continue)
  • 7.  Pros and Cons of using Function-like Macro • Function-like macro usage is just copy and paste, so no function call actually occurs which makes it faster than function call. • It is more difficult to debug in function-like macro code than normal function code. • Macros are error-prone because they rely on textual substitution: #define square(a) a*a /* works fine when used with an integer */ square(5); /* --> 5*5 --> 25 */ /* but does very strange things when used with expressions */ square(1+2); /* --> 1+2*1+2 --> 1+2+2 --> 5 */ square(x++); /* --> x++*x++ --> increments x twice */ 7 Preprocessor directives (continue)
  • 8.  Pros and Cons of using Function-like Macro Using parentheses around all your variables inside macro will help in first problem but not the second: #define square(a) ((a)*(a)) square(1+2); /* --> ((1+2)*(1+2)) --> 3*3 --> 9 */ square(x++);/*((x++)*(x++))-->still increments x twice*/ • Macros do not perform type-checking: #define MAX(A,B) (((A)>(B)) ? (A) : (B)) Then doing the following will not produce any error or warning: printf("%dn", MAX("abc","def")); But if the same was done with usal functions then the compiler will generate warning during compilation. 8 Preprocessor directives (continue)
  • 9.  Examples on preprocessor directives (continue): • Stringification: #define LED_INIT(PORT,PIN) printf("Initializing PORT: "#PORT" n"); portInit(PORT,PIN,OUTPUT); portState(PORT,PIN,LOGIC_HIGH) When we want to convert a macro argument into a string constant. So typing: LED_INIT(‘A’,3); will be the same as typing: printf("Initializing PORT: A n"); portInit(‘A’,3,OUTPUT); portState(‘A’,3,LOGIC_HIGH); 9 Preprocessor directives (continue)
  • 10.  Examples on preprocessor directives (continue): • Concatenation: It is used to merge two tokens into one while expanding macros. This is called token pasting or token concatenation. Suppose you have a function with 3 different implementations: portInit_implementation1(void); portInit_implementation2(void); portInit_implementation3(void); Then you can define: #define PORT_INIT(NUM) portInit_implementation ## NUM () Then to choose which function of the 3 to call using only PORT_INIT: PORT_INIT(2); it is the same as typing: portInit_implementation2(); 10 Preprocessor directives (continue)
  • 13.  Primitive Data Types • The primitive data types in c language are the inbuilt data types provided by the c language itself. Thus, all c compilers provide support for these data types. • The following primitive data types in c are available:  Integer Data Type, int: Integer data type is used to declare a variable that can store numbers without a decimal. The keyword used to declare a variable of integer type is “int”. Thus, to declare integer data type following syntax should be followed: int variable_name;  Float data Type, float: Float data type declares a variable that can store numbers containing a decimal number: float variable_name; 13 Data types
  • 14.  Primitive Data Types  Double Data Type, double: Double data type also declares variable that can store floating point numbers but gives precision double than that provided by float data type. Thus, double data type are also referred to as double precision data type: double variable_name;  Character Data Type, char: Character data type declares a variable that can store a character constant. Thus, the variables declared as char data type can only store one single character: char variable_name;  Void Data Type, void: Unlike other primitive data types in c, void data type does not create any variable but returns an empty set of values. Thus, we can say that it stores null: void myFunc(); /* Function returns void data type */ 14 Data types
  • 15.  Derived Data Types • A derived data type is a complex classification of a new data type that is made up of simpler primitive data type. Derived data types have advanced properties and uses far beyond those of the basic primitive data types that operate as their essential building blocks. • The following are examples for derived data types:  Array: a kind of data structure that can store a fixed-size sequential collection of elements of the same type. So instead of typing: int var1, var2, var3, var4; We can simply make them in array of 4 integers: int Arr[4]; /* Uninitialized */ OR int Arr[4] = {3,2,4,6}; /* Initialized */ Array consists of contiguous memory locations. The lowest index Arr[0] corresponds to the first element and the highest index Arr[3] to the last element. 15 Data types
  • 16.  Derived Data Types (Array continue) Array can be given value at declaration (Initialized array) or can have no initial values at declaration. Array should be fixed size, and size should equal number of initialization elements: int Arr[4]; /* Valid*/ int Arr[] = {3,2,4,6}; /* Valid, compiler will put size = 4 as it is initialized */ int Arr[]; /* Invalid, compiler error */ int Arr[2] = {5,6,7,8}; /* Invalid, compiler error */ Accessing array is through array name and element index: Arr[2] = 10; /* Change third element */ Exceeding array limits: int Arr[10]; /* Declare array of 10 integers*/ Arr[15] = 10; /* Will not produce compilation error, but at runtime it may cause a lot of problems (Data corruption, program termination, …) */ 16 Data types
  • 17.  Derived Data Types (Array continue) String doesn’t exist as a primitive data type in C language, but arrays can be used to represent string in an array of characters: char Arr[6] = ‚Hello‛; Note that array size is number of string characters + 1, this extra character is used to store the NULL ‘0’ terminator which marks the end of string, so the following will lead to same result: char Arr[6] = {‘H’,’e’,’l’,’l’,’o’,’0’}; This NULL terminator is used to know where string ends, for example when required to print the string: printf(‚%s‛, Arr) /* Will print Hello*/ Or by doing: int i = 0; while(Arr[i] != ‘0’) printf(‚%c‛, Arr[i++]); /* Will print Hello*/ 17 Data types
  • 18.  Derived Data Types (Array continue) Till now this is called 1-D (1 dimensional) array. In memory it looks like that: 18 Data types Arr[0] Arr[1] Arr[2] Arr[3]
  • 19.  Derived Data Types (Array continue) C language also provides a multi-dimensional array, for example we can create a 2-D array: int Arr[3][4]; Which can be considered as a table with 3 rows and 4 columns: 19 Data types column 0 column 1 column 2 column 3 row 0 Arr[0][0] Arr[0][1] Arr[0][2] Arr[0][3] row 1 Arr[1][0] Arr[1][1] Arr[1][2] Arr[1][3] row 2 Arr[2][0] Arr[2][1] Arr[2][2] Arr[2][3] Generally we can any number of dimensions: int Arr[size1][size2]………..[sizen];
  • 20.  Derived Data Types (Array continue) 2-D array initialization: int Arr[3][4] = { {1,22,13,40}, /* row 0 */ {7,4,45,7}, /* row 1 */ {23,34,83,47} /* row 2 */ }; It can be also initialized like that, but this is not recommended for readability: int Arr[3][4] = {1,22,13,40,7,4,45,7,23,34,83,47}; 20 Data types
  • 21.  Derived Data Types  Function: A function type describes a function with specified return type. A function type is characterized by its return type and the number and types of its parameters. A function type is said to be derived from its return type, and if its return type is int , the function type is sometimes called function returning int. /* Function that returns integer, and takes 2 parameters first is integer and second is character*/ int myFunc(int x, char y); This is called function declaration, or function signature. 21 Data types
  • 22.  Derived Data Types  Pointers: A pointer is a variable whose value is the address of another variable, i.e., direct address of the memory location: int Var1 = 10; /* Var1 is integer contains value 10 */ int *ptr = &Var1; /* ptr is pointer to integer, its value is the address of Var1 in memory*/ 22 Data types Memory Var1 = 10 0xFE00 Ptr = 0xFE00 0xFF04
  • 23.  Derived Data Types (Pointers continue) We can make the pointer points to another variable during runtime: int Var1 = 10, Var2 = 30; int *ptr = NULL; /* NULL Pointer points to nothing */ ptr = &Var1; /* Pointer now holds Var1 address */ *ptr = 20; /* Change Var1 value through pointer */ ptr = &Var2; /* Pointer now holds Var2 address */ *ptr = 50; /* Var2 will change to be 50 */ 23 Data types
  • 24.  Derived Data Types (Pointers continue) Pointer size: Pointer size depends on a lot of factors (hardware, operating system, compiler, etc.), and not all pointer types on the same platform may have the same size. For example, there are embedded processors that use a Harvard architecture, where code and data are in separate memory areas, and each may have a different address bus size (e.g., 8 bits for data, 16 bits for code). This means that object pointers (int *, char *, double *) may be 8 bits wide, but function pointers (int (*)()) may be 16 bits wide. So on 32-bits address bus controller: char *ptr; printf(‚%d‛, sizeof(ptr)); /* Print 4 bytes */ 24 Data types
  • 25.  Derived Data Types (Pointers continue) Pointer arithmetic: A pointer in c is an address, which is a numeric value. Therefore, you can perform arithmetic operations on a pointer just as you can on a numeric value but the result is different than normal variables. There are four arithmetic operators that can be used on pointers: ++, --, +, and - . When we type: long int Var1 = 10; long int *ptr = &Var1; ptr ++; If Var1 address is for example 1000, then pointer value at the start is the same as Var1 address which is 1000. After ptr++ the value of ptr will become 1004, which means it is incremented by 4 not just 1. Pointer increment by 1 will increment pointer value by the size of the variable it points at which is 4 bytes in our case. 25 Data types
  • 26.  Derived Data Types (Pointers continue) Another example: long int Var1 = 10; long int *ptr = &Var1; ptr += 3; If Var1 address is for example 1000, then pointer value at the start is the same as Var1 address which is 1000. Adding 3 to ptr will make ptr value becomes 1012, which means it is incremented by 12 (3 * 4 bytes = 12). The same for other increment and decrement operations. 26 Data types
  • 27.  Derived Data Types (Pointers continue) Pointer can point to any data type, for example pointer to array: long int Arr[5] = {10,20,30,40,50}; long int *ptr = &Arr[0]; This will make ptr points at the first element in the array so: printf(‚%d‛, *ptr); /* Will print 10 */ printf(‚%d‛, *(ptr+1)); /* Will print 20*/ printf(‚%d‛, *(ptr+2)); /* Will print 30*/ *(ptr+4) = 0; /*Will change last element in Arr to 0*/ Pointer can also be used like array with index: printf(‚%d‛, ptr[2]); /* Will print 30 */ ptr[4] = 3; /*Will change last element in Arr to 3*/ 27 Data types
  • 28.  Derived Data Types (Pointers continue) Pointer can be used to represent string like arrays used: char *ptr = ‚Hello‛; printf(‚%s‛, ptr); /* Will print Hello */ This is the same as typing: char ptr[] = ‚Hello‛; Note: Array name is itself a pointer to the first element in the array, but it is a constant pointer so Arr value can’t be changed by any means: char Arr[6] = ‚Hello‛; Arr++; /* Compilation error */ 28 Data types
  • 29.  Derived Data Types (Pointers continue) We can create an array of pointers: long Var1 = 1, Var2 = 2, Var3 = 3; long int *ptr[3] = {&Var1, &Var2, &Var3}; /* Now each element in ptr array is a pointer to variable */ printf(‚%d‛, *ptr[0]); /* Will print 1*/ printf(‚%d‛, *ptr[1]); /* Will print 2*/ printf(‚%d‛, *ptr[2]); /* Will print 3*/ 29 Data types
  • 30.  Derived Data Types (Pointers continue) We can have a pointer to pointer, which means that a pointer 2 holds the address of pointer 1, and pointer 1 points to any variable: long Var1 = 1; long int *ptr1 = &Var1; /* ptr1 points to Var1 */ long int **ptr2 = &ptr1; /* ptr2 points to ptr1 */ 30 Data types *ptr1 = 10; /* Will change Var1 value to 10 */ **ptr2 = 20; /* Will change Var1 value to 20 */ *ptr2 = NULL; /* Will change value of ptr1 to NULL */ Var1 = 1 Address 0xFF00 ptr1 = 0xFF00 Address 0xFFE4ptr2 = 0xFFE4 Address 0xFFF8 Var1 = 20 Address 0xFF00 ptr1 = NULL Address 0xFFE4ptr2 = 0xFFE4 Address 0xFFF8
  • 31.  Derived Data Types (Pointers continue) We can make a pointer to function: A function pointer is a variable that stores the address of a function that can later be called through that function pointer. int myFunc(char myChar) { printf(‚Character is %c‛, myChar); return 0; } /* inside any code */ int (*ptr)(char) = myFunc; /* Now ptr holds the address of function myFunc */ ptr(‘A’); /* Will call myFunc which will print A*/ (*ptr)(‘A’); /* The same as previous line*/ 31 Data types
  • 32.  Derived Data Types (Pointers continue) Pointers examples: what is the difference between all of this? int a; int *a; int **a; int a[10]; int *a[10]; int (*a)[10]; int (*a)(int); int (*a[10])(int); 32 Data types
  • 33.  Derived Data Types (Pointers continue) Pointers examples: int a; /* An integer */ int *a; /* A pointer to an integer */ int **a; /* A pointer to a pointer to an integer */ int a[10]; /* An array of 10 integers */ int *a[10]; /* An array of 10 pointers to integers */ int (*a)[10]; /* A pointer to an array of 10 integers */ int (*a)(int); /* A pointer to a function a that takes an integer argument and returns an integer */ int (*a[10])(int); /* An array of 10 pointers to functions that take an integer argument and return an integer */ 33 Data types
  • 34.  User Defined Data Types Sometimes, the basic set of data types defined in the C language such as int, float etc. may be insufficient for your application. In circumstances such as these, you can create your own data types which are based on the standard ones.  Structure: a kind of data structure that can store a collection of elements that are not of the same type. For example: struct carInfo { int speed; float batteryLevel; double kilometers; char bodyTemperature; }; This is called structure carInfo data type declaration, but till now there is no variable of that type exists. 34 Data types
  • 35.  User Defined Data Types (Structure continue) To declare a variable of type carInfo: struct carInfo myCar; /* Uninitialized */ OR struct carInfo myCar = {0, 0, 0, 0}; /*Initialized*/ To edit any value of variable structure members: myCar.speed = readCarSpeed(); myCar.batteryLevel = readBatteryLevel(); myCar.kilometers = readCarKilometers(); myCar.bodyTemperature = readBodyTemperature(); 35 Data types
  • 36.  User Defined Data Types (Structure continue) We can define a pointer to structure: struct carInfo *ptr = &myCar; /*ptr points to myCar*/ Editing structure members through pointer is achieved through arrow operator -> ptr->speed = readCarSpeed(); 36 Data types
  • 37.  User Defined Data Types  Union: A union is a special data type available in C that allows to store different data types in the same memory location. You can define a union with many members, but only one member can contain a valid value at any given time. Unions provide an efficient way of using the same memory location for multiple-purpose: union U_data { int Var1; double Var2; char Var3; }; To declare a variable of type U_data : union U_data test; /* Uninitialized */ OR union U_data test = {0}; /*Initialized*/ 37 Data types
  • 38.  User Defined Data Types (Union continue) Union members share the same memory location, so editing any member’s value will corrupt other members’ values: test.Var1 = 32; /* all other members are now 32*/ test.Var2 = 10;/* first 2 bytes of the union memory contains value 10, other 2 bytes are not changed*/ Size of Union variable test is the size of the biggest union member (double in our example). Using union saves memory, but a big caution should be taken to track which member contains valid data. 38 Data types
  • 39.  User Defined Data Types  Enum: An enumeration is a user-defined data type consists of integral constants and each integral constant is give a name: enum week {sunday, monday, tuesday, wednesday, thursday, friday, saturday}; First element in enum by default takes value 0 if not initialized explicitly, so sunday will have value 0, monday will have value 1 and so on. Usage: enum week today; /*Declare variable of type enum week*/ today = Wednesday; /* today value now is 3*/ 39 Data types
  • 40.  User Defined Data Types (Enum continue) enum members can be initialized with default values: enum week {sunday=5,monday,tuesday,Wednesday=9,thursday, friday, saturday}; Now sunday will have value 5, monday 6, tuesday 7, but wednesday will be 9 not 8, then thursday 10 and so on. Note: Multiple members can have the same value, but member name can’t exist twice. We can add boolean data type to C language using enum: enum boolean{ false, true}; enum boolean check; /* Now we can use check as boolean */ 40 Data types
  • 41.  User Defined Data Types  typedef: We can define any data type we want from another data type using typdef keyword: typedef unsigned char uint8; typedef unsigned short uint16; typedef unsigned long uint32; typedef unsigned long long uint64; Now we can use the new defined data types: uint8 Var1; /*Var1 is unsigned char*/ 41 Data types
  • 42.  User Defined Data Types (typedef continue) typedef with structure: typedef struct carInfo { unsigned long speed; unsigned short batteryLevel; unsigned long kilometers; unsigned char bodyTemperature; } Car_Type; Now instead of typing: struct carInfo myCar; We can type: Car_Type myCar; 42 Data types
  • 43.  User Defined Data Types (typedef continue) We can simulate the behavior of typedef using #define like that: #define uint8 unsigned char uint8 Var1, Var2;/*Var1 and Var2 are now unsigned char*/ But the problem arises when trying something like that: typedef unsigned char* u8_ptr_Type; #define u8_ptr_Define unsigned char* u8_ptr_Type ptr1, ptr2; /* Both will be pointers */ u8_ptr_Define ptr3, ptr4; It is expected that both ptr3 and ptr4 are of type pointers to unsigned char, but because #define is just text replacement then what really happens is that previous line is replaced with: unsigned char* ptr3, ptr4; Which will make ptr3 successfully a pointer, but ptr4 will be normal variable. 43 Data types
  • 44.  Declaration vs. Definition Declaration: A declaration tells the compiler the type of a variable, object or function, but doesn’t allocates memory for it or know all function details. extern uint8 Var1; /* Variable extern */ void myFunc(uint8 Var2); /* Function prototype */ This is particularly useful if you are working with multiple source files, and you need to use a function or variable in multiple files. You don't want to put the body of the function or same variable in multiple files statically, but you do need to provide a declaration for it. Then in only one file you can put the definition. 44 Data types
  • 45.  Declaration vs. Definition Definition: A definition allocates memory for a variable or object and is the implementation of a function. uint8 Var1 = 10; void myFunc(uint8 Var2) /* Function Definition*/ { printf(‚myFunc definitionn‛); } Multiple declarations are allowed, but only one definition. 45 Data types
  • 46.  Overflow vs. Underflow Overflow: It is the condition that occurs when a calculation produces a result that is greater in magnitude than the maximum value that a given register or storage location can store or represent. Unsigned overflow: unsigned char Var1 = 255; Var1++; /* Overflow */ printf(‚%d‛, Var1); /* Prints Zero */ Signed overflow: signed char Var2 = 127; Var2++; /* Overflow */ printf(‚%d‛, Var2); /* Prints -128*/ 46 Data types
  • 47.  Overflow vs. Underflow Underflow: It is the condition that occurs when a calculation produces a result that is smaller than the minimum value that a can be stored. Unsigned underflow: unsigned char Var1 = 0; Var1 -= 8; /* Underflow */ printf(‚%d‛, Var1); /* Prints 248*/ Signed underflow: signed char Var2 = -128; Var2 -= 3; /* Underflow */ printf(‚%d‛, Var1); /* Prints 125*/ 47 Data types
  • 48.  Type Casting Type casting is a way to convert a variable from one data type to another data type. For example, if you want to store a 'long' value into a simple integer then you can type cast 'long' to 'int'. Explicit casting: You can convert the values from one type to another explicitly using the cast operator as follows: (type_name) expression Example: int Var1 = 8, Var2 = 20; float Var3 = (float) Var2 / Var1; Implicit casting: Implicit casting doesn't require a casting operator. This casting is normally used when converting data from smaller integral types to larger or derived types to the base type: Var3 = Var2; /* Var2 value is implicitly converted to float and put inside Var3*/ 48 Data types
  • 50.  Data Type Qualifiers • Apart from the mentioned primitive data types, there are certain data type qualifiers that can be applied to them in order to alter their range and storage space and other properties to fit in various situations as per the requirement. • The data type qualifiers available in c are:  Size modifier: affects size (number of bytes): short int variable_name; /* 2 bytes integer */ long int variable_name; /* 4 bytes integer */  Sign modifier: affects values range: signed int variable_name; /* can have negative range */ unsigned int variable_name; /*can’t have negative range*/  Constant modifier: affects ability to change it during runtime: const char Var = ‘A’; /* can’t change at runtime */ 50 Data Type Qualifiers
  • 51.  Primitive Data Types Summary with size and sign modifiers 51 Data type Size Value range char 1 -128 to 127 or 0 to 255 unsigned char 1 0 to 255 signed char 1 -128 to 127 int 2 or 4 -32,768 to 32,767 or -2,147,483,648 to 2,147,483,647 unsigned int 2 or 4 0 to 65,535 or 0 to 4,294,967,295 short 2 -32,768 to 32,767 unsigned short 2 0 to 65,535 long 4 -2,147,483,648 to 2,147,483,647 unsigned long 4 0 to 4,294,967,295 Data Type Qualifiers
  • 52.  Primitive Data Types Summary with size and sign modifiers 52 Data type Size Value range Precision float 4 1.2E-38 to 3.4E+38 6 decimal places double 8 2.3E-308 to 1.7E+308 15 decimal places long double 10 3.4E-4932 to 1.1E+4932 19 decimal places Data Type Qualifiers
  • 53.  Data Type Qualifiers It should be noted that the size and sign modifiers cannot be applied to float and can only be applied to integer and character data types.  Volatile modifier: tells the compiler that this variable can change outside of the code control (ex. HW Register value): volatile char Var = 10; if (Var == 10) { /* Any code*/ /* If variable was not declared volatile, the compiler may optimize this part by considering the condition always True and remove the if condition check ! */ } When a variable is declared volatile, any reference for that variable makes the compiler reload its value from RAM again to make sure it is the last updated version of that variable. 53 Data Type Qualifiers
  • 54.  Data Type Qualifiers  Storage classes: A storage class defines the scope (visibility) and life-time of variables and/or functions within a C Program. o auto: The auto storage class is the default storage class for all local variables. int variable_name = 20; o register: The register storage class is used to define local variables that should be stored in a register instead of RAM. This means that the variable has a maximum size equal to the register size and can't have the unary '&' operator applied to it (as it does not have a memory location). /* Compiler will try to put this variable inside processor registers */ register int variable_name = 10; 54 Data Type Qualifiers
  • 55.  Data Type Qualifiers  Storage classes: o static: The static storage class instructs the compiler to keep a local variable in existence during the life-time of the program instead of creating and destroying it each time it comes into and goes out of scope. Therefore, making local variables static allows them to maintain their values between function calls. The static modifier may also be applied to global variables or functions. When this is done, it causes that variable or function’s scope to be restricted to the file in which it is declared. o extern: The extern storage class is used to give a reference of a global variable or function that is visible to ALL the program files. When you use 'extern', the variable cannot be initialized and function can’t have a body however, it points to variable or function name that has been previously defined in another file. 55 Data Type Qualifiers
  • 56.  Data Type Qualifiers  Storage classes: 56 File1.c static int variable_1 = 10; int variable_2 = 20; File2.c static int variable_1 = 50; extern int variable_2; /* Then inside any part of code */ printf(‚variable_1=%d, variable_2=%d‛, variable_1, variable_2); /* It will print variable_1=50, variable_2=20 */ Data Type Qualifiers
  • 58.  Scope 58 Scope and Lifetime Local scope File scope Global scope
  • 59.  Scope • The area of our program where we can actually access our variable is the scope of that variable.  Local scope: visible within function or statement block from point of declaration until the end of the block. void myFunc() { uint8 Var1 = 10; { uint8 Var2 = 11; printf(‚%d, %d‛, Var1, Var2); } printf(‚%d‛, Var2); } Var1 is visible inside all myFunc, but Var2 is only visible inside its inner block { } which is a local inner scope. 59 Scope and Lifetime
  • 60.  Scope  File scope: visible within current file only, but its is visible to all functions inside this file, by using static keyword with variables or functions. 60 Scope and Lifetime File1.c static int Var1 = 50; void myFunc1() { printf(‚%d‛, Var1); } void myFunc2() { printf(‚%d‛, Var1); } File2.c void myFunc3() { printf(‚%d‛, Var1); } File3.c static int Var1 = 20; /* Same name, but totally different variable */
  • 61.  Scope  Global scope: visible everywhere, it is defined in one file, and all other files can use it using extern keyword. 61 Scope and Lifetime File1.c int Var1 = 50; void myFunc1() { printf(‚%d‛, Var1); } void myFunc2() { printf(‚%d‛, Var1); } File2.c extern int Var1; void myFunc3() { printf(‚%d‛, Var1); }
  • 62.  Lifetime • Life time of any variable is the time for which the particular variable outlives in memory during running of the program.  Automatic: An automatic variable has a lifetime that begins when program execution enters the function or statement block or compound and ends when execution leaves the function or block. Automatic variables are stored in a "function call stack". void myFunc() { uint8 Var1 = 10; { uint8 Var2 = 11; /* Var2 scope and life time ends here */ } /* Var1 scope and life time ends here */ } 62 Scope and Lifetime
  • 63.  Lifetime  Dynamic: The lifetime of a dynamic data begins when memory is allocated (e.g., by a call to malloc()) and ends when memory is deallocated (e.g., by a call to free()). Dynamic data are stored in "the heap". /* Allocate 1000 bytes in RAM (Heap part) */ uint8 *myData = (uint8*) malloc(1000); /* Any code */ free(myData); /* Data is deallocated, so its life time ends here */ 63 Scope and Lifetime
  • 64.  Lifetime  Static: A static variable is stored in the data segment of the "object file" of a program. Its lifetime is the entire duration of the program's execution. Static variable is initialized only the first time function is entered, and its value remains in memory between function calls. void myFunc() { static uint8 Var1 = 10; printf(‚%d‛, Var1); Var1++; } First call to myFunc will print 10, second call 11, third call 12 and so on. 64 Scope and Lifetime
  • 66.  What is Make (GNU Make as an example) • GNU Make is a tool which controls the generation of executables and other non-source files of a program from the program's source files. • Make gets its knowledge of how to build your program from a file called the makefile, which lists each of the non-source files and how to compute it from other files. When you write a program, you should write a makefile for it, so that it is possible to use Make to build and install the program. 66 Makefile introduction
  • 67.  Capabilities of Make • Make enables the end user to build and install your package (in case you provided them with source code) without knowing the details of how that is done because these details are recorded in the makefile that you supply. • Make figures out automatically which files it needs to update, based on which source files have changed. It also automatically determines the proper order for updating files, in case one non-source file depends on another non-source file. As a result, if you change a few source files and then run Make, it does not need to recompile all of your program. It updates only those non- source files that depend directly or indirectly on the source files that you changed. • Make is not limited to any particular language. For each non-source file in the program, the makefile specifies the shell commands to compute it. These shell commands can run a compiler to produce an object file, the linker to produce an executable, ar to update a library..etc. 67 Makefile introduction
  • 68.  makefile structure • Make searches for a file called makefile without any extension to do its work. • Basic building elements of make file are:  Target: What is the output of current step.  Dependencies: What should be already available to start making current target.  Commands: What should be done to make current target. All of them are called “Rule”. A rule in the makefile tells Make how to execute a series of commands in order to build a target file from source files. It also specifies a list of dependencies of the target file. This list should include all files (whether source files or other targets) which are used as inputs to the commands in the rule. 68 Makefile introduction
  • 69.  makefile structure • Rule structure: 69 Makefile introduction • Target name is typed at start of line, then followed by a colon : then followed by list of all dependencies that should be available to start executing commands, then on each new line write a new command to be executed, each command should have a Tab space before it or the make will not work. • Dependencies can be on one line, or can be divided on multiple lines: Target: dependency1 dependency2 ... commands ... Target: dependency1 dependency2 dependency3 ... commands ...
  • 70.  makefile structure • Rule example: 70 Makefile introduction D:newProject>make file.o file.o: file.c gcc -c file.c -o file.o Create any C code file with the name file.c and put it in the same directory with the makefile. Then by running Make through command line: Create a text file with the name makefile without any extension and type the following inside it:  The Make utility will search for the file makefile, then it will search inside it for the required target file.o .  It will search what are file.o dependencies, it will find that it only depends on file.c.
  • 71.  makefile structure  It will check “is the required dependency file.c available ?”, the Make file will find it in the same directory.  After the Make utility finds file.c, it will execute the commands under file.o target which is here compiling file.c, so the output of this command will be: 71 Makefile introduction D:newProject>make file.o gcc -c file.c -o file.o  Now you will find in the same directory a file created called file.o which is the compiled output file of file.c .
  • 72.  makefile structure • If the Make didn’t find the required dependency file, it will search if this dependency is another required target then do it first: 72 Makefile introduction app.exe: file1.o file2.o gcc file1.o file2.o -o app.exe file1.o: file1.c gcc -c file1.c -o file1.o file2.o: file2.c gcc -c file2.c -o file2.o Create a C code file with the name file1.c which contains the main function, create another C code file file2.c with any code, and put them in the same directory with the makefile.
  • 73.  makefile structure 73 Makefile introduction Run the Make and the output will be: D:newProject>make app.exe gcc -c file1.c -o file1.o gcc -c file2.c -o file2.o gcc file1.o file2.o -o app.exe Now you will find in the same directory a file called app.exe which is the compilation output.
  • 74.  makefile structure • If the Make didn’t find the required dependency file in the directory or as any other target then it will generate this error and stop: 74 Makefile introduction D:newProject>make newFile.c make: *** No rule to make target `newFile.c'. Stop. • If Tab space doesn’t exist before any command then Make will generate this error and stop (note that 5 is number of first line containing error): D:newProject>make app.exe makefile:5: *** missing separator. Stop. • When you run Make, you can specify particular targets to update; otherwise, Make updates the first target listed in the makefile. Of course, any other target files needed as input for generating these targets must be updated first.
  • 75.  makefile structure • Usually makefile contains 2 targets called all and clean to be used by any one without knowing the details of our makefile content: 75 Makefile introduction # all target is usually put as the first target all: app.exe clean: rm file1.o file2.o app.exe app.exe: file1.o file2.o gcc file1.o file2.o -o app.exe file1.o: file1.c gcc -c file1.c -o file1.o file2.o: file2.c gcc -c file2.c -o file2.o
  • 76.  makefile structure • So typing all target will output the same result as typing app.exe, and typing clean target will delete file1.o, file2.o and app.exe . 76 Makefile introduction D:newProject>make clean rm file1.o file2.o app.exe • clean and all targets are called “Phony Targets”. A phony target is one that is not really the name of a file, rather it is just a name for a recipe to be executed when you make an explicit request, it may have dependencies like all target and may not have any dependencies like clean target.
  • 77.  Make variables • A variable begins with a $ and is enclosed within parentheses (...) or braces {...}. Single character variables do not need the parentheses. Example: 77 Makefile introduction CC = gcc file1.o: file1.c $(CC) -c file1.c -o file1.o
  • 78.  Make variables • Automatic Variables: Automatic variables are set by make after a rule is matched. They include: $@: the target filename. $*: the target filename without the file extension. $<: the first prerequisite filename. $^: the filenames of all the prerequisites, separated by spaces, discard duplicates. $+: similar to $^, but includes duplicates. $?: the names of all prerequisites that are newer than the target, separated by spaces. 78 Makefile introduction
  • 79.  Make variables Example 1: 79 Makefile introduction file1.o: file1.c $(CC) -c $< -o $@ # It is the same as typing $(CC) -c file1.c -o file1.o Example 2: OBJ_FILES = file1.o file2.o app.exe: $(OBJ_FILES) $(CC) $^ -o $@ # It is the same as typing: # $(CC) file1.o file2.o -o app.exe
  • 80.  Make variables Example 3: 80 Makefile introduction OBJ_FILES = file1.o file2.o LINK_TARGET = app.exe CLEAN_TARGET = $(LINK_TARGET) $(OBJ_FILES) all: $(LINK_TARGET) # It is the same as typing: # all: app.exe clean: rm $(CLEAN_TARGET) # It is the same as typing: # clean: rm file1.o file2.o app.exe
  • 81.  Make implicit rules Implicit rules are a set of generalized instructions for doing certain tasks, where the instructions are provided as default. For example, an implicit rule can tell Make utility how to construct a .o file from a .c file without explicitly typing files names. Example 1: 81 Makefile introduction %.o: %.c $(CC) -c $< -o $@ # It means ‚whenever you find a required target with #any name but with extention .o and there is no #explicit rule for how to make this target, then #execute the next commands on this target.
  • 82.  Make implicit rules Example 2: 82 Makefile introduction %.o: %.c $(CC) -c $< -o $@ file1.o: file1.c $(CC) -c file1.c -o explicit_file1.o app.exe: file1.o file2.o file3.o $(CC) $^ -o $@ # For file2.o and file3.o it will use the implicit #rule, so their output names will be file2.o and #file3.o but for file1.o it will find an explicit rule #for it then it will execute it, so its output name #will be explicit_file1.o
  • 83.  Creating project hierarchy Most of the time the project contains different folders, not just all source and headers files in the same place, for example if we need to make one folder for source code files with name “src” and another folder for header files with name “inc”, then in the makefile we should do the following (assuming that the makefile is in the same directory as both folders): 83 Makefile introduction # Tell makefile Where to find source files vpath %.c ./src # Header files path INCLUDE_PATH = ./inc %.o: %.c $(CC) -c -I$(INCLUDE_PATH) $< -o $@ # -I$(INCLUDE_PATH) tells the compiler where to find #header files
  • 84.  Header files issue After running make all, if we edited any source file the Make utility will recompile this file only and targets that depends on it. But if we changed any header file the make utility will not even notice and will not make any recompilation for the source code that depends on this file which we don’t want. This is because we didn’t tell the Make utility any thing about header files dependencies inside the makefile. That’s why we should make dependencies generation, which makes the compiler enters all source files, extract information about what header files that each source file depends on, generate a corresponding dependency file for this source file and include this information in our makefile. After making these steps, whenever we change a header file, any source file that depends on this header file will be recompiled and any target that depends on this source file will be made again. 84 Makefile introduction
  • 85.  Header files issue (solution) 85 Makefile introduction # Generate dependencies list # Dependencies output path DEPS_PATH = ./dep/ # Source files path SRC_PATH = ./src/ # Header files path INCLUDE_PATH = ./inc/ # Get source files names with path SRC_FILES_ABSOLUTE = $(wildcard $(SRC_PATH)*.c) # Get source files names without path SRC_FILES = $(patsubst $(SRC_PATH)%.c,%.c,$(SRC_FILES_ABSOLUTE))
  • 86.  Header files issue (solution) 86 Makefile introduction # Make dependencies names the same as sources names but with extension .d DEPS_FILES = $(patsubst %.c,%.d,$(SRC_FILES)) # Get dependencies files names with their path DEPS_FILES_ABSOLUTE = $(patsubst %.d,$(DEPS_PATH)%.d,$(DEPS_FILES)) # Rule to make dependencies files $(DEPS_PATH)%.d : %.c # Generate dependencies files (Small make file for each c file) $(CC) -MM -MP -MT$@ -I$(INCLUDE_PATH) $< -o $@
  • 87.  Header files issue (solution) 87 Makefile introduction # Include all dependencies make files inside current make to be #used in #linking target to detect when any header file changes -include $(DEPS_FILES_ABSOLUTE) # Add dependencies to our target app.exe: $(OBJ_FILES) $(DEPS_FILES_ABSOLUTE) $(CC) $^ -o $@
  • 88.  Make simple complete example Create 3 different folders: • src: contains all your source files. • inc: contains all your header files. • dep: empty, will be the output for dependencies files. Create empty text file with the name makefile without any extension and put the following inside the file: 88 Makefile introduction
  • 89.  Make simple complete example 89 Makefile introduction # Tell makefile Where to find source files vpath %.c ./src # Compiler used CC = gcc # Dependencies output path DEPS_PATH = ./dep/ # Source files path SRC_PATH = ./src/ # Header files path INCLUDE_PATH = ./inc/
  • 90.  Make simple complete example 90 Makefile introduction # What is our target name LINK_TARGET = app.exe # Objects used later to be linked to generate our link target OBJ = main.o Func1.o Func2.o Func3.o # What will be used at clean target CLEAN_TARGET = $(LINK_TARGET) $(OBJ) # Used with > make all all:$(LINK_TARGET) echo Bulding done !
  • 91.  Make simple complete example 91 Makefile introduction # Used with > make clean clean: rm $(CLEAN_TARGET) echo Cleaning done ! # What will happen when requiring $(LINK_TARGET) $(LINK_TARGET): $(OBJ) $(DEPS_FILES_ABSOLUTE) $(CC) $(OBJ) -o $@ echo Linking done ! # What will happening when requiring any target with any file name with #extension .o %.o: %.c $(CC) -c -I$(INCLUDE_PATH) $< -o $@ echo File $< compilation done !
  • 92.  Make simple complete example 92 Makefile introduction # Generate dependencies list # Get source files names with path SRC_FILES_ABSOLUTE = $(wildcard $(SRC_PATH)*.c) # Get source files names without path SRC_FILES = $(patsubst $(SRC_PATH)%.c,%.c,$(SRC_FILES_ABSOLUTE)) # Make dependencies names the same as sources names but with extension .d DEPS_FILES = $(patsubst %.c,%.d,$(SRC_FILES)) # Get dependencies files names with their path DEPS_FILES_ABSOLUTE = $(patsubst %.d,$(DEPS_PATH)%.d,$(DEPS_FILES))
  • 93.  Make simple complete example 93 Makefile introduction # Rule to make dependencies files $(DEPS_PATH)%.d : %.c #Generate dependencies files (Small make file for each c file) $(CC) -MM -MP -MT$@ -I$(INCLUDE_PATH) $< -o $@ # Include all dependencies files inside current make to be used in #linking target to detect when any header file changes -include $(DEPS_FILES_ABSOLUTE)
  • 95. Mohamed AbdAllah Embedded Systems Engineer mohabdallah8@gmail.com 95