Kirans C notes



“ADVANCED ‘C’ LANGUAGE”

Program is a set of instructions given to a computer to do particular task (OR) A Group of instructions is also called as program.

There are so many languages like c, c++, java etc..

Why there are so many languages?

There are so many types of applications and domains, according to the type of domain we will go for a language which is better for that application.

E.g.: java is most preferable for web applications. C++ is favour for windows graphics & system side programming and C is especially very favour to interact directly with hardware.

Languages are designed by some person. That person doesn’t bother about the compilation and executions. Some third party vendors will provides the compilers. Compilers will check only syntactical errors. Syntactical errors means weather the keywords (or) library functions exist (or) not. It will check that only it doesn’t bothers about the logical errors.

A logical error means e.g. c=a/b is a valid statement. By getting the values to a and b, consider if b as given “zero” and a is 5 then Compiler will not find that as a error because it was syntactically correct but logically incorrect. Debuggers will checks the logical errors. Any compiler can check the syntactical errors but Debugging tools can only finds logical errors.

Compilers are mainly TWO types:

1. IDE COMPILERS.

2. COMMAND LINE COMPILERS.

IDE - integrated development environment compilers e.g.: RIDE, KEIL. Etc

COMMAND LINE - Turbo, bollard, Etc

Source file is something which understands by the user. After compilation of source file we will get object file. Object file is raw binary.

We can get executables in two methods from object file.

1. Real mode (embedded mode)

2. Protected mode.

Real mode is nothing but directly interacting with CPU. There is no OS.

In protected mode there is a OS which could not understand the raw binary.

Here is a linker which converts the raw binary to understandable format for both OS and CPU.

Executable file is something which both OS and CPU can also understand

Source file

compiling Compilation

Executables are platform

Dependent .here platform means

OS+CPU

Object file

build process

Linker

Executable file

• Object file is CPU specific but OS independent

Q) We have (windows +32) bit object file. Can we run this object file on Linux + 32 bit platform to create executable.

A) Yes certainly because executables are platform dependent. Object file is CPU specific and OS independent.

Program is a collection of data and instructions. Once, after writing and giving a program to a CPU the following process will done.

If any program (or) application is loaded into system. By default that will be stored in the HARD DISK.

Once we start execution of program the stored program in HARD DISK is sends the particular file to RAM which we want to execute. Then RAM is having both data and instructions. By taking that data and instructions from the RAM, CPU will executes that data according to the instructions.

Data: - Nothing but raw supply

Instruction:- Is some thing what process has to be done with the data. (int a=10, b=20,c;- ( data)

(c=a+b; ( instruction)

Language:- a set of rules which a programmer has to fallow is called a language.

Data types

Basically C follows 5 data types.

1. int

2. float

3. char

4. double

5. void.

Writing “C” programs on Linux platform.

Enter into Linux mode

Press Alt+F2, a small box will be open enter console and press enter it will opens an editor.

(Or)

Given a right click on mouse open a net terminal it also opens an editor. Next we can give an instruction (vim filename.c)

Directly we can’t write programs in that editor we have to enter into insert mode by pressing ‘’I’’ key on the key board (or) insert button on the key board. Then we can freely write programs. After completion of programs. Writing in that editor press escape button and press: wq write and quit (or) save and quit.

Next for compilation we have to give the following command

Gcc filename.c – output file name, then output file name given the output

Variable: is an identifier given to a piece of data.

Constants: In ‘C’: constant is a piece of data which can be of following type

Integer constant

Real number constant

Single char constant

Set of char constants.

Constants are identified (or) referred with some names called as variables (or) symbol names.

Syntax: data type variable name

Int a;

Float b;

Char c; etc.

After defining the variables only we can use those variables in the program.

Before making use of any variable in a ‘C’ program first we need to define the variable.

Variable definition will tells us TWO types

1. Name of the variable

2. What type of data is pointing to?

Int - 4 bytes

Float - 4 bytes

Double - 8 bytes

Char - 1 bytes

Float is single precision.

Double is double precision.

Combination of data and operators is called expression. In expressions we will have operands and operators here operands can be variables (or) constants.

A+b + is an operator, a, b are operands

10+50 + is an operator, 10, 50 are operands.

Operators are divided into 2 types depending upon the number of operands are required to operate on data.

1. Unary operators.

2. Binary operators.

Operator: operator is a special character whose behavior is predefined and which will always performs the given task on some operands.

Unary operators:- ++,--, size of (), logical not !.

‘C’ supports ++ and -- unary operators which can also be called as unary increment and unary decrement operators. These operators can be used in 2 phases. Depending upon how the operator appears with operands.

1. Post increment a++

2. Pre increment ++a

If operator appears after operand then it is called as post increment and it has the least priority.

If operator appears before operand then it is called as pre increment and it has the highest priority.

Same is applicable for decrement operator also.

Size of (int) ------- 4 bytes brackets after size of is purely optional.

! Logical not is also come under unary operator

Size of (expression) --------- expression can be a constant variable (or) keyword.

Binary operator:-

i) Arithmetic operators: +, - , * , / , % each and every operator returns (some value)

Each and every operator always works with the same type of data.

All operators can perform the given task on same type of data.

The return value of any operator depends upon the operator which we are using and the type of the operands.

Assignment is simply like (L value = R-value); here L value always must be a variable.

R-value may be constant, variable (or) expression.

II) Relational operator:- >, =, b, a>c;

Pf (“a is big”);

a>b>c is not valid.(this is invalid statement)

III) Logical operator:-

&& - logical AND

|| - logical OR

! - Logical NOT

Logical AND Logical OR

Op1 op2 o/p op1 op2 o/p

0 0 0 0 0 0

0 1 0 0 1 1

1 0 0 1 0 1

1 1 1 1 1 1

Int a=10, b=20, c=30, d;

d= a>b&& a>c; valid

d= a&&b; valid

Syntax: op1 logical Operator op2

Here operands op1 and op2 are operands which can be constants (or) variables (or) expressions.

IV) Shorthand operator:- command assignment operators it can also be called as arithmetic assignment operators.

+=

-=

*=

/=

%=

➢ Compound assignment operators are always used as shorthand operators for arithmetical operations.

➢ Compound assignment operators always require 2 operands one on left side and the other one is on right side of the operator. The left operand should always be a variable of any type except strings.

➢ Compound assignment operators will take the rvalue applies on lvalue and result is again stored in lvalue.

Conditional operator:-

Syntax: exp1? exp2: exp2

Conditional operator is a very special and peculiar operator in “C”

There is no other operator in ”C” operates more than operands. 2

From the syntax esp1 will decides the output of the conditional operator.

Exp1 is true operator returns exp2, if exp1 is false exp3 returns.

Eg: int a=10, b=20, c;

C= b>a?, b:a;

In ‘c’ language any operator returns some value that value may be either ‘0’ or other than ‘zero’

In ‘c’ if an operator returns zero its always a false statement.

If an operator return other than zero that may e (1,-1,-0,-01) anything considered as a true statement.

E.g. int a=10,b=2;

B=a? a:b; valid statement and it return a value to b.

Depending upon the storage capacity data types are again divided into 2 types.

1. Single byte data

2. Multi byte data.

Single byte data – char, void.

Multi byte data - int, float, double

Weather the data is single byte or multi byte it will store in the memory by following the rule of byte order.

Byte order is nothing but how data is representing in memory cells.

Data type tells that how many bytes have to occupy byte order tells how to represent data in RAM.

Byte order is TWO types:

1. Little Endean.

2. Big Endean.

INTEL and AMD processors follow little Endean.

Motorola processors follow big Endean.

MODIFIERS: modifiers are mainly used to change (or) modify the properties of the data types these are special instructions given to data types.

Modifiers are mainly 2 types.

1. Signed modifiers.

2. Size modifiers.

Signed modifiers are again 2 types

1. Signed.

2. Unsigned

Signed modifier is the default modifier which will be applied to any variable definition if modifier is not specified. Signed modifiers will reserve one bit to tell weather the given number is positive or negative. This will be useful when we need operator on both +ve and –ve data. Max limit is 231 -1

Unsigned modifiers tell that we are going to use only +ve data. There is no need of signed bit representation in this . max limit is 232-1

Signed and unsigned are applicable for all types of data int, float, double, chat.

Size modifiers are again 2 types.

1. Short.

2. Long.

These are used to modify the size of the data short is the modifier which will always used with in tint reduces the size to 2 bytes.

Long is the modifier which can be used with both int and double.

Long int = 4 bytes

Long double = 12 bytes.

Short and long are not applicable for float because in ‘c’ it must be 4 bytes to represent a floating point data. So short is not applicable already double is there to represent floating points with 8 bytes. So there is no need for double also.

Printf(“ any characters (or) dummy representation”);

Printf(“conversion chars”, variable list);

Variable list separated by comma(,) operator.

In printf function escape characters (starts with \) and conversion char (or) format specifier (starts with %) having some special meaning other than these two anything will be written on the output device as it is.

Here when we are writing a printf with format strings we have to remember two things.

1. No. Of conversion chars must always be equal to no. of variables.

2. A variable has to write in the same order how the format strings are written in double quotes in printf.

Rules followed by “c” while evaluating arithmetic operator.

1. If any one of the operand in arithmetic expression is float the result is double.

2. If both operands are int the result is also int.

3. If any one of the operand is double result double.

4. If any one of the operand is long double the result is also long double.

5. If any one of the operand is long int the result is also long int.

6. If nay one of the operand is short(or) char the result is int.

We know that we have ALU inside CPU. This ALU will perform only integer expressed operations.

Q) Here we will have a question? Who will perform operations on float?

A) Inside processor we will have FPU. FPU will take care of the operations on floating point data.

In same 16 bit processors we don’t have FPU there we have some algorithms to perform floating operations.

Whenever we are doing operation on one int and one float, the FPU temporarily converts the int to float and floating operation will carries out

If we want to store a higher bytes data into lesser sized then we will get the overflow result.

Type casting operator: type casting operator is used to convert one data type to the other. We can convert any type of data type to the other type with type casting operator.

Syntax: (type) operand.

Type casting operator is purely unary operator as it works only on one operand.

Operands can be variables, constants (or) expressions.

E.g. int a=7, b=2;

I) Float(a);

II) Float(a/b);

III) Float (7);

E.g.: in second one float (a/b) a will be type casted as float. Compiler converts be to float. But a good programmer himself converts b also float.

So float (a)/float (b). By giving like this we can reduce the compilation time.

E.g.: float a=7.23, b=2.4

Int (a)/b gives float result only because any operand is float the result is a double so if we need output as int we have to write the above expression as

Int (a)/int(b).

Then we will get result also int.

Precedence of operator: in ‘c’ each and every operator is having precedence.

Precedence is nothing but priority of the operator which will have to evaluate first in the given expression.

Some operators in ‘c’ is having the same priority then what we should have to do?

E.g. *, /, % operators in ‘C’ are having the same priority.

In that case we will follow the associatively of the operator.

Associatively means when we are evaluating some expression contains the same priority operators more than once then associatively tells the evaluation from left to right (or) right to left.

++,--,type cast, size of R to l

*,/,% L to R

+,- L to R

=,>,>=,20):---- expressions allowed at case constant. With pure constant

Nits.

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

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

Break;

Case 10:

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

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

Default:

}

Case constant must be as int (or) char like’A’.

If no statement needs to execute after switch body in a program then we go for return in place of break;

Order of labels is not mandatory in C language even default: also if should not lay at the end. It can be anywhere in the switch. It is other than at the end requires break (or) return.

No need to write break to the last label of a switch case. That last label may be a case constant (or) default.

LOOPS:

1) WHILE: Whenever we need to execute a statement or set of statements more than one time repeatedly. We will go for loops.

“C” supports 3 types of loops.

1. While

2. Do-while

3. For.

While loop is a iterative control statement. That allows the code to be executed repeatedly based on the given controlling expression. The while (controlling exp) consists of a single or Block of statements along with controlling exp.

Syntax: while (controlling exp)

{

Body of Statement1;

The while Statement2;

Loop Statement3;

}

The while loop first evaluates the controlling exp and if controlling exp returns true, statements present in the while body gets executed, it repeats this process until the controlling exp returns falls. Because the while loop checks the controlling exp before the body of the loop is executed, it is often called as “pre –test loop”

In “C” generally loops requires the basic following rules.

1. Loop counter definition

2. Controlling exp

3. Loop count increment or decrement.

Where loop counter is a variable use with loops and controlling exp tells when to come out of the loop. Controlling exp should be returning such a way that at some point it returns false value. If controlling exp always returns true then such loops are called as add loops (or) infinite loops which will never end.

DO-WHILE :

In do while loop irrespective of the control exp in while the do body will executes once. After executing the do body the controlling exp will checked. If controlling exp is true if again goes to do body if false if just terminates from the loop.

Do

{

Statement1;

Statement2;

Statement3;

} while (controlling exp);

In do while loop there must be semicolon at the end of while.

FOR LOOP:

For (initialization; controlling exp; increment (or) decrement

{ exp2 ` exp3

Statement1;

for body Statement2;

Statement3;

Statement n;

}

Q) We already have while loop then what is the purpose of going to for loops?

A) In for loop at the time of defining for itself we will give initialization, controlling exp and increment (or) decrement , so there is no chance of forgetting anyone in the loop. Where as in while loop we have to give the increment and decrement values. If we forget those in while body we may get infinite loop and sometimes serious problems also.

Q) How for loop will work?

A) In for loop control first comes to the initialization part. After initialization control goes to the next exp which is controlling expression, where the control checks the condition if the controlling exp is true then control enters into for body. After executing all statements in for body control goes to the next exp3. Which is increment and decrement? After incrementing or decrementing the value the control goes to the exp2, where the condition again checks. If the condition is true it enters into the body if fails our of the loop.

All three expressions in for loop are optional. The syntax exactly is given below to for loop.

For (init (opt, & multi); control exp (opt); increment (or) decrement (opt, multi))

For (; ;) infinite loop.

Unconditional controlling structure:

Break: the break statement terminates he execution of the nearest enclosing do, for while (or) switch statement in which it appears.

Control passes to the next immediate statement following the above mentioned statements.

Continue: continue statement passes the controller to the next iteration of the nearest enclosing does, for (or) while statement in which it appers.

Goto: the goto statement transfers the controller to a label. The given label must reside within the same function where you have used goto statements. Labels can appear after (or) before goto statements. It’s a good programming style to use break, continue (or) return statements instead of go to.

Goto is very useful and dangerous. It is architecture dependent. Whenever we need to portable that to one platform to another go to may behave differently.

As go to is unconditional statement we can take the controller in the (program) function by keeping a lable.

If we misplace a label we may get problems.

So as a good programmer maximum try to avoid go to in programs and check for alternatives.

Memory concept:

“C” internals: the “C” view of memory devides the memory into 5 types.

1. Text section

1. Data section

2. Bss section (block storage segment)

3. Stack section.

4. Heap section.

Text : the text section contains the code (or) instructions of the program as well as constants used by the program. The data stored in this section never changed this is read only section.

Stack: temporary data (or) local data is stored in stack section. All variable defined within a blocks will e part of stack section.

Physical memory: RAM is the physical memory available in sizes like 128,256,512 (MB) and 1 GB , 2 GB like that. In that each and every location is represented with one address which is also represented by the designer itself.

Whatever the address designed on the RAM is called physical memory.

Logical memory: logical address is something which doesn’t exist actually but appears to be existing. The “OS” uses manage the logical memory.

E.g. assume we have 512 MB RAM.

The logical addresses will generate for 512 MB RAM is 2512 locations.

CPU will generate logical addresses but the generated logical addresses will be managed by the “OS” to mapping the logical address to physical address.

Q) How logical memory will come?

A) With the help of MMU register inside the CPU; CPU will generate logical address.

Expiation for mapping:

Let us define a variable int a;

Int a; means that compiler is asking the CP that a need 4 bytes then “OS” come into picture and generates 4 bytes of logical memory to that. Here at int a it doesn’t store anywhere so here there is no topic of physical memory.

Int a=4;

Here 4 is assigned to a so it has to store. Some where that has to store that is physical memory.

While declaration of variable it assign’s some logical address. While initializing that to 4, that logical address is mapped to some physical address and gets stored at RAM’s physical memory.

Once the execution of the program is completed the memory mapping but logical and physical memories gets (evoperated) break.

Multi tasking : multi tasking is something we can work with many operations at a time. But CPU processes only one task at a time then how multi tasking is existing the reason is time sharing.

OS will shares the time for each and every process in equal amounts of time, but our eye can’t identify that speed.

Just assume we have 10 tasks. We open all. OS allots time to all processes. First process is running, if it completes within the shared time it is well and good. If within time it is not able to finish what will happens? That process stops and the process is stored into hard disk. Whenever its time comes back after all the shared remaining 9 tasks them again OS fleches the data from that hard disk and processes the data. The memory mapping logical addresses may vary in the second run of the process.

This is how the multi tasking will works.

For each and every process in the 10 processes each time of their time comes memory mapping will done. So each time with the process memory mapping will evoperates.

Q) if we not assigning values to variables, sometimes we will get garbage value why?

A) garbage is something which already existed in the physical memory stored by some other process previously. On evoperating memory mapping the values which stored in physical memory remain unchanged. Those values are garbage for the other programs

RAM contains a table to manage both logical and physical addresses for that time.

---------

FUNCTIONS: “C” programs needs minimum one function at least we can use ‘n’ number of functions in “C” there is no limit.

To use functions 2 things are necessary

1. Function body (or) function definition

2. Invoking the function.

DEF: function is a self set of instructions which always performs a particular task.

Q) why functions introduced in C?

A) the main purpose of functions used in C is REUSABILITY. Once a function is defined in “C” we can use that function anywhere in the program in many number of times.

A program contains only one function means that must be main ( ) function.

Q) When we go for functions?

A) Whenever we need a set of instructions at different , different places in a program then we go for functions.

Functions are of 2 types.

1. Pre defined functions.

2. User defined functions.

Predefined functions: the functions already defined and stored somewhere in the compiler are called predefined functions. “C” library is one which holds all these predefined functions.

“C” library contains all pre defined functions in OBJ format.

Eg: printf( ) , scanf( ) etc.

User defined functions: the functions who will be defined by the user and also used by the user.

The general format of “C” function definition.

Function name( )

Start print

{

Statement 1;

Statement 2;

Statement n;

} end point.

• Function names must be unique within the program.

Main ( ) is also user defined function. Except the name of the function.

Because as a user of main ( ) we only have to define the main function. So all the program have to perform will be given by OS only that’s how the main ( ) is user defined function.

Q) How to use functions?

In general if any functions we want to use. Means it should have to define first and it should has to invoked by some other function that may be predefined (or) user defined.

Main ( ) is the function which tells the compiler that from where to start the execution of the program.

The function which invokes by the other function is called, “called function”. The function which invokes that called function is called calling function.

Main ( )

{

----------

----------

----------

Demo ( ) ;

-------

-------

--------

}

In the above eg main( )is the calling function demo ( ) is the called function.

Add ( )

{

Int a=10, b=10;

Printf (“%d\n”, a+b);

}

Main( )

{

Add( );

----------

----------

----------

Add ( );

}

In the previous example in main we called add( ) function 2 times.

Two times if prints only 20. If we need both the times addition but not the same values than we go for sharing of values.

Add(int a, int b)

{

Int c;

C=a+b;

}

Main( )

{

Int d,e;

Add( 4, 6 ) (or) add (d,e) ;

Pf(“%d”, c);

}

In the example printf takes garbage value because “C” is local to called function. So if it want to return “C” to main function in “C” we should need another variable to catch the returned variable.(or) return value.

Called function always returns only one value to calling function.

So above eg: can be modified as

Add(int a, int b)

{

Int c;

C=a+b;

Return c;

}

Main( )

{

Int z,x,y;

Z=add(x,y); actual parameters

Printf(“%d”\n”, z);

}

In the above example main( ) is sharing the data with some called function. That called function processes the data and return that result to main.

By using parameters 2 things must be remember.

1. Num – ber of parameters passed by the calling function must be equal to the number of parameters in called function.

2. Data types sending with the calling function has to match with the received data types in called function.

Return single exp (or) var (or) constant;

Function names are also like variable name, but the difference is variables stores the data at some memory location.

Function also print to some memory location but where the self set of instructions will store.

Q) by default program will starts execution at main ( ) . According to ANSI standards someone has to invoke the function in “C” program. Then who is the one who invoke main ( )?

A) Shell is the one invokes the main( ) every program in “C” by default returns some value. Main returns the value to shell.

Main ( )

{

Int a;

A=disp ( ) pf(“%d”,a);

}

Disp ( )

{

Print(“’kiran’s embedded solutions”);

}

The above program gives no error. Because there is no syntactical error. Though we avoid the return type default “C” takes int. and the above function returns 5. The number of charge in printf.

Each and every function has exit state, to main( ) we only have to give the exit state that is return o;

The exact “C” program is this

Int main ( )

{

--------

-------

---------

Return 0;

}.

The exact def of a function is

Type function name ( arguments if required)

{

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

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

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

}

Diagram

all instruction in main( ), disp ( ) and demo( ) will store at different, different locations in logical memory.

Whenever shell invokes main( ), the memory location where main( ) instruction are started execution sequentially. Whenever we encounter disp( ) and demo ( ) in main ( ), control goes to that memory location part where those are stored and geets executed.

After completion of the program execution the physical to logical memory chain breaks.

FUNCTION DECLARATION:

Function declaration tells the compiler that what is the return type of the function, function name and the types of the parameters and also no.of parameters.

Syntax: type function name (type, type, type------);

Once function declaration is done compiler rises error if we give wrong return type of the function (or) if number of arguments not match ( or ) if not type of arguments not match.

|Header files holds all predefined function declarations, vardeclarations with extern keyword and macro definitions |

Void is also a return of a function which should not return any value.

STORAGE CLASSES:

Storage classes tell us 3 things about a variable.

1. Scope

2. Lifetime

3. Where to store in memory.

The actual syntax to declare a variable is * storage class modifier type variable;

SCOPE:

Scope comes in to picture after declaring a variable in a program. After declaration of the variable scope tells that where to use that variable where not to use that variable. Again scope is fall under 5 categories.

1. Program scope

2. File scope

3. Function scope

4. Block scope

5. Function prototype scope

• If a variable is having program scope we can use that variable anywhere in the program.

• Variables are sued within that file.

• Only lables in a “C” program are having function scope.

• All local variables having block scope the variables which are having block scope will not be accessed outside that particular block.

• Function prototype scope will be within that function declaration. i.e. any variable declared within the function prototype.

LIFE TIME:

How much time the value will bee preserved in the memory is life time of that variable. Scope and lifetime both are interrelated.

There are mainly 4 types of storage classes.

1. Automatic

2. Static

3. Register

4. Extern(or)global.

AUTO: scope of auto is local to block. Life time of auto is local to block. Auto variables always stored in stack memory section if we call a function 5 times each and every time it allocates new memory location.

STATIC: scope of static is local to block. Lifetime of static is till the program terminates. Static variables stores in BSS section. For static variables memory will store only once that too only at compile time. Default value for a static variable is ZERO.

In general the memory is allocated at runtime for local variables, whereas for static variables memory address location (logical memory) is allocated at compile time itself.

Eg: main()

{

Int a=10;

Static int b=a;

}

The above program gives the error because we could not assign any variable to static variable. For a static variable we have to assign a pure integer constant.

Eg: main()

{

Static int a=10;

Static int b=a;

}

The above program is also not valid because though both the variables are static we can’t assign any type of variable to static variable. In the above eg only memory is allocated at the time of compilation means that only addresses are allocated. At the time of run time only 10 is assigned to a, but a not assigned to b, because at run time it will not find any static variables definitions due to no physical memory is available.

NOTE: no formal arguments in any function could not use static variables, because static variables as parameters will not find at run time.

All static local variables have the entire program scope. Static variable definition gets executed only once at compile time.

Q) Advantages of defining static in main ()?

A) static variable defined inside the main() have no use as all local variables of main() will exists till the program terminates.

Q) What is the main use of static?

A) whenever we are invoking a function many times and all the times it needs to preserve that value for the next call then static is useful.

NOTE : for both auto and static scope is local to block where as comes to life time it differs, life time is also local to block for auto but for static it is entire program.

REGISTER: scope of register is local to block. Life time of register is also local to block. Register variables stores inside the CPU registers. By using register variables we can access the variables very fast, because there is no need to go to hard disk and fetched to RAM and then into CPU. Register variables are directly available in the CPU.

Register int a;

Register variables may or may not store inside the CPU. That will be decided by the compiler at the time of compile time. If it is not stored in the CPU registers means those will store in RAM’s stack memory section.

A variable defining as a register means we are telling to the CPU that the variable is using more frequently in the program. That we are telling through ‘C’ compiler. That compiler may be any. Any variable defined as a register have no address. So we can’t access the address of a register variable.

GLOBAL : scope is till the program terminates. Life time is also till the program terminates. Global variables stores in data section and BSS section. Any variable defined above all the blocks in the program is called as global or external variable.

NOTE : the global values initialized at the time of definition will store in data section and un-initialized global variables will store in BSS section.

All global values resolves at run time that means the memory will allocated at the time of compilation itself. The value of a global variable change in one function reflects the value in entire program. The default value for global is ZERO.

We can declare static also as global variables. As we know that storage classes will tell about 3 things, beyond these 3, storage classes tells about linkage also. Linkage is something which is used to create an executable from object files.

LINKAGE : linkage tells that after variable definition wheter that variable is used in same file or some other source file. LINKAGES ARE OF 3 TYPES

1. External linkage.

2. Internal linkage.

3. No linkage.

EXTERNAL LINKAGE: by default all global objects have external linkage. Global objects with external linkage will have program scope.

INTERNAL LINKAGE: global objects with static keyword have internal linkage. Static storage class with global and internal linkage will have file scope.

NO SCOPE: no linkage is also a type of linkage. All local variables have no linkage.

Q) what is program scope and what is file scope?

A) sharing a program among different persons or a program is divided as different modules and done all modules individually and combined to create an executable is called program scope. file is individual module scope.

NOTE : To create an executable from different files we need to take care that in all those files only one file has to be contained main().

Q) difference between definition and declaration?

A) variable definition asks for memory. Variable declaration will not asks for memory.

Extern in a; // declaration variable declaration tells the compiler that the variable ‘a’ is defined somewhere in the program externally. Whereas variable definition allocates memory for that variable.

We can access the global variables in some other source file by using declaration.

Ex:

1.c 2.c

Int a; //definition extern int a; //declaration

Main( ) a=10;

{

---------

Disp ( ) the value initialized in 2.c will

Reflects to all function in 1.c also

}

Note:

All functions in “C” by default have external scope and external linkage. Functions also have to declare in other source files if we need to access those in that file.

//function definition //function definition

Void disp( ) extern void disp( );

{

Printf(“kiran’s embedded solutions”);

}

In “C” language one variable can defined only once in the program and declarations can done at ‘n’ number of times in the program.

Q) how internally executable will generate in “C”?

DIAGRAM

Compiler will never see our source file, compiler have expanded source file as input.

IMP: compiler will look only one source file at a time where as linker will look all object files at a time and it links all the obj files to create an executable. Executable contains complete information about variables.

DIAGRAM

All global object definitions with external linkage will have two tables

1. Export

2. Import

There are some other tables also for time being these we take.

Export tables contains all definitions of global variable import tables contains all declaration of global variable.

Assume that we have given a command

Gcc 1.c 2.c 3.c

“a” is defined in 1.c and declared in 2.c and 3.c

First compiler sees 1.c it allocates memory to a ad creates an object file. Next compiler sees 2.c and assumed by looking the declaration that a is defined somewhere externally and creates object file in the same way for 3rd source file also, compiler creates an object file.

After creating all the object files linker comes into picture and links all the object files and creates an executable.

PRE PROCESSOR: pre processor processes our source file. After pre processing we will get translated unit code.

Pre processor is a separate language, it has its own instructions.

Each and everything in “C” programming, pre processor takes that as a token (or ) a string.

Eg: int a=10;

In the above eg preprocessor assumes that int is one word and a=10; is one string.

If we give int a=10;

Int, a, =,10, ; all are different, different words for preprocessor

• Pre processor removes all comments in our source file comment won’t look by compiler.

• \is the special char used to attach more than one line we come across in the source file.

• Those all different lines also make as a single line by preprocessor does the source file to tokenization.

IMP: tokenization is something converting code one form to other.

all preprocessor instructions are called preprocessor directives. Each and every directive starts with # symbol.

#include< > is the header file which just copies all instructions of that herder file and past’s those into or program.

We have different directives

1. Defines some data directives.

2. Function directives.

3. Controlling directives.

IMP: pre processor variables are called “MACROS” macro is preprocessor variable name refer to some data. No memory will be allocated for macros.

Syntax : #define name definition

# define macro value.

#define a 10

“C’” preprocessor supports 2 types of macros

1. Object like macros.

2. Function like macros.

Preprocessor won’t touch the instructions which will understandable by compiler but not by preprocessor.

Preprocessor keeps those as it is .

Macros are nothing but symbolic constants.

Object like macros are defined like

# define Uint, unsigned int

Main( )

{

Uint a; (un signed int a);

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

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

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

}

Function type macros will define as

# define add(x , y) x+y

1. add(10,20);

2. add(10.5, 2.5);

3. add(‘a’, ‘b’);

4. add(“Veda”, “kiran”);

all the above statements are valid for compiler and pre processor, but 4th statement is not valid for compiler.

#define name (arguments) definition

Eg: #defind max(x,y) x>y?x:y.

#define add(x,y) x+y

Main( )

{

Add(10,20);

Add (10.5 2.5);

Add(‘a’, ‘b’);

Add(“kiran”, “kumar”);

}

From the above eg: two strings we cannot add,

Drawback is function like macros is this only, that is we can’t restrict the user to give particular type of arguments because everything for preprocessor is a string. So the forth statement is not a valid statement for compiler.

Function like Macros may look like function invocation statement, but function like macros arguments can’t be defined for a specific type everything is a string for preprocessor.

So always we need to define the macros in such a way that after replacement it should be valid statement for “C” compiler.

The only difference between object like macros and functions like macro is arguments function like macros takes arguments object like “ “ No arguments.

Whenever we are working with macros up to some extent of the program we requires one value for the macro and later we require another value with the same name then we go for redefining a macro.

Redefining macros in 2 types

1. undefined the macro and redefine the macro with the same name.

eg: # define max 100.

Int main( )

{

-------

---------

#undef max

--------

---------

#define max 200

-----

------

}

2. we can directly redefine the macro without undefined the existed macro

#define max 100

Int main( )

{

-----------

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

#define max 200

}

From the above eg we can say that undefined macro is optional.

• Macros don’t have any scope and lifetime.

Header files contains only 3 things

1. Macro definitions

2. Predefined function prototypes

3. Variable declarations with extern keyword.

Macro will do just replacement.

There are some pre defined macro also. We have 3 types of predefined macros also.

1. Language specific macros way compiler is having language specific macros.

2. Compiler specific macros compiler designing people will define these macros.

3. System specific macros these macros will be designed by OS people

Linux compilers having version numbers major number, minimum number and path number.

All “C’” header files in Linux exists in /user/include.

We have to define the macros such that after preprocessing the source file, the generated translated unit must be valid input for the compiler

Eg; #define macro *kirans embedded solutions*

Main( )

{

Pf(“%s”, macro);

}

This is not valid for the compiler

#define macro “kirans embedded solutions” this is valid statement for compiler

If we want to pass a string as argument

#define macro(s) #s

Main( )

{

Pf(“%s”, ”kirans embedded solutions”);

}

We can write any string in that printf here the #symbol before S is called stringification operator

Stringification:

whenever macro definition should act like a string constant for the compiler we will use # operator with their definitions # operator is called stringificatin operator which returns the given definition with in “ “.

Concatenation operator:

whenever we want to concatenate 2 arguments of a function like macro we will use double hass (##)

concatenation operator concatenates 2 strings of a function like macro arguments and returns as a single value.

#define STR (S1, S2) # (S1 ## S2)

Main ( )

{

STR ( kirans embedded solutions)

Pf(“%s”, STR(kirans embedded solutions));

}

The above gives kirans embedded solutions

The # before (s1 ## s2 ) gives the entire concatenated string in double quotes.

# define STR (S1, S2) S ((S1 ## S2))

# define S (a) #a.

Preprocessing supports conditions compilation.

Conditional compilation is done according the conditions which we defined for preprocessor.

1. ## def it always checks whether macro is defined or not.

2. # if n def this is exactly opposite to # if def, we will tell the preprocessor that if not defined do something.

3. # if this allows us to evaluate expression same like if.

4. # else

5. #el if

6. #end if

# if is also used to check whether a macro is defined or not by using the following statements.

# if defined macro

#define max 100

#define min 10

Int main( )

{

--------

--------

# if def max

-----------

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

# end if

----------

-----------

#ifn def max

-------

--------

# end if

#if max >=100

-------

-------

# end if

#if defined max

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

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

# end if

}

#define max 0

Main( )

{

---------

---------

# if def max

Printf (“defined”);

#end if

# if max

Printf(“defined”);

#end if

---------

---------

#if defined max

Printf(“defined”);

#end if

}

Whenever we need to share function declarations and macros in different source files of a program we need to include files like.

Each and every compiler have its own default search path

#include default search path

#include “stdio.h” obsolete path

Compilation starts from the resent working directory and ends at default search path.

Q) if we include some header file multiple times what happens?

A) all the times it includes that file, it wastes so much memory.

Q) what should we have to do if by mistake we have a include a file multiple times?

A) to avoid recursive inclusion of header files we will define one macro within the header file and we check whether the macro is already defined or not? If that macro is defined header file no included, if not defined header file include. To accomplish this we will make use of conditional directives.

Eg: include

Include

# if ndef my

Float add (int, int0;

Int demo (float)

#define my

#end if

Gcc –d positive ifdef.c

In general # include , like standard headerfile will follow this conditional directives only.

-D is the option of gcc command to define macros at command prompt while compilation.

Gcc –I/ demo’c

This command temerorily to default search path. Of the header file.

-I- for preprocessor

-L- for linker.

Varidic functions: veridical functions are very special functions, these are used whenever we don’t know the number of arguments has to pass and the type of the arguments to hold .

In general all printf and scanf functions are defined with varidic functions only because. Possing arguments and type of arguments to printf and scanf is varied from time to time according to the application requirementns.

Syntax of varidic function is type func-name(. . .)

If we find 3.s in any function it is a varidic function.

Varidic functions has the flexibility to take no.of arguments and the type of the arguments.

To handle varidic functions some set of macros are already predefined

Those are va-list int add(. . . );

Va_short. Add (2,10,20);

Va_arg. No.of arguments

Arguments to add

Va_list obj; if holds variable length arguments.

Va_start (obj, arguments )this arguments is fixed.

Any varidic function always must and should contain at least one fixed argument va_arg( , ),

Beyond function in “C” C99 supports inline functions.

Inline function:

all the time of function invocation if replaces the entire program at the definition itself we have to mansion that inline keyword.

Inline int add (intx, inty);

{

}

Inline functions are useful in small function definitions. It is not useful for large functions because those occupies more memory.

With the definition of the inline function we are telling the compiler that we are going to use this function frequently.

As like register storage class it may. Also treated as inline (or) ordinary functions.

Pointers

Pointer is a derived data type which allows us to define a variable which has the ability to store address of another variable.

Syntax: type * variable;

Type followed b ‘*” tells that variable is a pointer variable.

We can use pointer variables to any type.

Int * double * float * char * void *

Eg: int p=10; //value 10 store in p

Int *p=10; // address 10 stored in printer p

Each and every address is un signed. Because there is no address with –ve values.

Size of address is always equals to the word size of the architecture.

For any architecture .int =pointer = word size.

Pointers always deals with 2 special chars.

1. *

2. &

1.* ‘*’ is used to define a variable

‘*’ is used to dereference the pointer

2.* ‘&’ address operator.

These both are pure unary operators under pointers. Because both will operate on single operand.

We can initialize pointers in 3 types.

Int a=10, *p;

P= &a; 1

P= 0; 2

P =null 3

Null is a macro which already defined except these 3 forms we can’t assign any value to pointer variables

DEREFERENCEING:

Pointers are having the capacity to fetch the value present in the variable which address that pointer is stored. Is dereferencing .

To print the addresses of a pointer we use %p , % x, %u (conversion characters)

Null pointers are something which pointing to no where pointers stores logical addresses only.

The type of the pointer is telling that at the time f dereference how many bytes has to retrieve.

Pointers always deal with the similar type of variables.

Int a;

Char*p =&a // invalid.

Double b=10.5;

Int *p =&b // invalid.

We can’t perform addition, subtraction (or) any arithmetic operations on two pointers.

Int *p, *q

P+q //invalid;

We can use limited operations and limited operators on pointers.

++ increment

--decrement.

+ - with some restrictions.

We can use size of, relational and logical also.

We can use additions (or) subtraction with pointers is given below: pointer + variable (int, char) constant (“ ,”).

Int a,b,c,=10, *P;

B= p+a;

P+c;

P+10;

*,/,% we can’t operate on pointers.

Wild pointers:

The pointers which are defined but not initialized properly are called wild pointers. So we can’t use the pointers without proper initialization.

Sometimes wild pointers terminates our application. Because of wild pointers we will get some segmentation faults.

Memory violations are called segmentation faults segmentation faults are pure RUN TIME errors. Due to security purpose as will terminates the applications

Void pointer:

Void pointer is the one which can store any type of data. Void pointers are also called as generic pointers.

Void *p;

Int a p =&a;

Float b p= &b;

Double p =&d;

We can’t derefer the void pointers directly void pointers are dereferred by using type casting type casting temporarily changes the operations.

Int a=10;

Void *p; dereferencing through

*(int*) p; type casting

(4 bytes)

*p; 1 byte.

Beyond modifiers we have 2 specifiers.

1. Const

2. Volatile.

Const int a; const int a=10;

The state of the const variables voill no be change throughout the program.

Const keyword only have read only permissions const is a pure compile time statement.

Q) we can define constants through macros also, what is the difference between macro and const?

A) ma

RAM won’t have read only memory locations. RAM has read. Write memory locations.

Compiler will check the illegal operation on the const symbol compiler won’t allow any operations on censt variables. Compiler will try to remove all the statements which area trying to change const values.

Const variables has to initialized at the time of definition itself.

Macros won’t occupy memory.

Const occupies memory.

Const float pi; float c;

Pi; 3.14; //error

C= pi+1; initialization is not possible after definition of const variable.

Eg: const int a=10;

Int *p =&a;

*p =20; // valid.

From the above eg. We can tell that const values can also be changed by using pointers.

So by that we can tell that there is no security.

Q) Then how can we provide security for const variables while using pointers?

A) While using pointers we can provide security to const variable by applying const to pointer at the time of initializing address to the pointer.

Const int a=10;

Const int *p =&a ; (or) int const *p = &a;

This is printer pointing to constant.

Q) What to do if pointer itself is constant.

Int * const p // const is nearest to pointer const is the keyword it should bound its properties nearest to the type.

Const int * const p =&a;

Const pointer itself is pointing to a constant.

We can’t derefer a void pointer until and unless we type cast that.

Even we can’t perform any operations on void pointers gcc allows us to increment void pointers.

Invoking the function with their address is called call by reference. There is no need of return statement in called function.

Main ( )

{

Int a=10, b=20;

Swap (&a, &b);

Printf(“%d %d”, a,b);

}

Swap( int *a, int *b)

{

Int temp +*a;

*a = *b;

*b =temp;

}

Generic functions always written by void pointers.

ARRAY:

Array is a collection of sequential memory locations used to store similar type of data. Array is also a derived data type.

Derived data type are derived from primitive data type.

Whenever we need to store number constant with a single variable name then we go for arrays. Those constants may be, int, char, float, double etc.

Syntax: type name [size]

Int a[5];

INITIALIZING ARRAY:

Initialization of arrays is possible at the time of definition and also later like ordinary variables.

Int a[5] ={1,2,3,4,5}

(or)

A[0] = 1;

A[1] = 2;

A[2] = 3;

A[3] = 4;

A[4] = 5;

Offset always starts from 0 and ends with size -1.

Offset = index = suffix = subscript .

Array variable always gives the starting address of the array.

Size of array always pure. Int constant according to ANSI standards variable lenth arrays are not supported.

Int a=5;

Int b [a]; //ansi error but gcc allows.

Q) Variable length arrays are not initialized at the time of definition why?

A) Variables are resolved at run time. So without knowing the values how culd we assign the values to array. That’s why we don’t initialize the values to variable length arrays.

At compile time compiler will treat a[5] as a[ ], that’s all.

The size of array must always be pure int constant index is the one which used to manipulate individual elements of the array.

Pointers and arrays are inter related.

Eg: letus assume we have defined an array.

Int a[5];

Pf (“%U”, a) (&a or a)

By default it will display the starting address of the array. The type tells that , this array going to store interger type of data.

But internally it takes as a[b] address. Whenever we increment a value as a[0] to a[1] there inside the processor that increments 4(or)8 bytes according to the type because internally that array gets stroed as a pointer variable. A[0] =*(a+0), a[1] =* (a+1).

There is no difference in writing an array as a[5]; and 5[a] index is no was helpful at RUNTIME.

By using indexes only compiler manipulates dereference internally.

Logical addresses are sequential but not physical. Physical may (or) may not sequential.

Q) function always returns only one value then how could we return all array values?

When we are dealing with arrays by default it passes the starting address of the array while we call that function. That called function the format arguments catches this address and they act as a pointers. Because pointers stores addresses, and it takes 4 bytes that may be any type.

Int main( )

{

Int a[5] ={1,2,3,4,5,};

Add (a); call by reference

}

Void add ( int b[5] (or) (int *p) both are correct .

{

Int i-0;

For (;i ................
................

In order to avoid copyright disputes, this page is only a partial summary.

Google Online Preview   Download