Sei sulla pagina 1di 10

C Language Notes

Of

Narender Rao Saineni,M.Tech(IIT) ns@itagesolutions.com

Data Types:
Built in Data types
Char Integers: Short short int Int Long long int Long long Floating point : Float Double Long double 8 16 32 32 64 32 64 64

could be 2B for some architectures

This gives us the idea that 32 bit architecture implements all types of data Int , float in 32 bit natural size. Only when we want long long int , or double float we need 64 bit.

Abstract data types:


Bit fields: Struct struct_tag{ Unsigned sex:1 Unsigned :1 Unsigned age:6 }

//name not neccessary

The ordering of the bits may be from left to right or right to left The size of the bit field will be in terms of one word or more words. One bit field can not be present across the word boundaries. Enum enum_tag{RED,BLACK,WHITE}

Scopes:
Block Function

File Function prototype

Type qualifiers:
Const Volatile

Storage class specification:


Auto Register Static Extern

{ extern is applied for global or local data}

Macros Type Definitions

Control Constructs:
Break: Break works in loops and switch block , it does not work in if blocks Continue: In a loop it skips the loop block beyond this statement and goes for the next iteration If struct is defined like Struct fraction{ Int numerator; Int denominator; } to instantiate it you need to use the struct keyword like struct fraction f1;

typedef example typedef

built in typeofdata/structure howwedefineit long int T_BIGINT

Directives:
Directives are always introduced by a line that starts with a # character, optionally preceded by white space characters (although it isn't common practice to indent the #). Table 7.1 below is a list of the directives defined in the Standard. Directive
# include # define # undef # if # ifdef # ifndef # elif # else # endif # line # error # pragma #

Meaning include a source file define a macro undefine a macro conditional compilation conditional compilation conditional compilation conditional compilation conditional compilation conditional compilation control error reporting force an error message used for implementation-dependent control

null directive; no effect Table 7.1. Preprocessor directives

Macros:
#define MAXCOUNT 10000 define replaces the defined symbol with its value parameterized macros can be used i.e macro functions #define ABS(value) ( if value>0 return value; else return value;)

#define FMAC(a, b) printf("%s %s\n", a, b) FMAC ("hello", "sailor" ); /* results in */

printf("%s %s\n", "hello", "sailor")

static keyword before function means the function is visible within the current file. The static keyword before a global variable is redundant, every global variable is static. Static keyword before a local variable means the variable is stored in the stack but in the heap and has persistence like global variable.

Operators:
*p++ what does it do ?
The order of evaluation of unary operators is from right to left, so ++ is performed before *. Compund operator X+=y X=x+y; means

p->x++ increments x ++p->x so does this! (++p)->x *(p->y)++ *(p++)->y increments p before getting x so does this uses y as a pointer, then increments p *p->y++ uses y as a pointer, then increments it

The way to remember these is that ->, . (dot), ( ) and [ ] bind very tightly. An expression involving one of these is treated as a unit. p->x, a[i], y.x and f(b) are names exactly as abc is.

(Expr1)? (trueaction) : (false action)

Function Pointer usage:

Void (funcptr*)(int a, char b); Void greater(int a, char b); Funcptr=greater;

// function pointer declaration

Assert
While you are debugging programs, it is often useful to check that the value of an expression is the one that you expected. The assert function provides such a diagnostic aid. In order to use assert you must first include the header file <assert.h>. The function is defined as
#include <assert.h> void assert(int expression)

If the expression evaluates to zero (i.e. false) then assert will write a message about the failing expression, including the name of the source file, the line at which the assertion was made and the expression itself. After this, the abort function is called, which will halt the program.
assert(1 == 2); /* Might result in */ Assertion failed: 1 == 2, file silly.c, line 15 Assert

is actually defined as a macro, not as a real function. In order to disable

assertions when a program is found to work satisfactorily, defining the name


NDEBUG

before including <assert.h> will disable assertions totally. You should

beware of side effects that the expression may have: when assertions are turned off with NDEBUG, the expression is not evaluated. Thus the following example will behave unexpectedly when debugging is turned off with the #define NDEBUG.
#define NDEBUG #include <assert.h>

void func(void) { int c; assert((c = getchar()) != EOF); putchar(c); }

Example 9.2 Note that assert returns no value.

Dividing an application into modules:


The set of functions doing a related task is a module. A module is kept in a file The module should have a public interface i.e header file And private implementation is .c file The header file should contain the interface of declarations of public functions. The data structures and the public constants. The private functions and the data members should be in the c file. The interface should consist of simple functions , not complicated ones. The implementation c file should declare all its private data and functions as static . So that they are not accessible from other modules. The declarations of private functions should be in the c file. The information exchange or interaction between the modules should be minimum. The header file should be verbose , i.e self documenting type because that is all others have to look at to use the module. It should contain a comment section at the beginning describing what the module does and what routines are available what they do within the comment section. Then constants Then data structures Then function declarations. Every function should have function comment block before the declaration. Describing

What the function does, as one line or so What are the inputparameters What it returns And any comment like warning etc.

Exception handling methods for robust code:


Reference: http://freetype.fis.uniroma2.it/david/reliable-c.html Exception types: User input out of range Resource not available(memory, port) Bugs in the program like pointer pointing to junk Handling exceptions, by extra run time checks - checking assertions like assert(p!=NULL) // will pass silently if TRUE else will print the assert fail, in file , at line so and so to stdout/stderr assert is a macro defined in assert.h - checking the result of function from system or library Paranoid way of handling exceptions: Return error code from every function and check it and take action on every function return. Simpler method is to abort the application with status print in case of error without returning error code from the function. Works ok if the system is not of 24 hour running type. Setjmp longjmp method We have to set aside a static jump_buffer to store the current IP and registers values. Store the buffer higher up with the program state . deep down some where where error is encountered call longjmp. The program restores to the stored state . what about the partial resources allocated ? Setjmp return with non zero value, upon this non zero value branch is taken to the exception handling code. This code should release the resources . the resources taken should be stored in a state object user implemented.

Code template using setjmp and longjmp; Struct { Jump_buffer Void * Port Semaphore }state; main(){ if jbuffer; p1,p2 port1 s1

(setjmp(state.jbuffer)==0){ do something

// returns 0 first time called

if error some where deep down within any function longjmp(state.jbuffer,1); } } else { //error handling release the resources , take pointers from the state. }

SEH: Structured Exception handling Using TRY ,CATCH blocks // try catch in C can be implemented with macros Based on setjmp and longjmp. CSEH: Cleanup Stack Exception Handling This is a more elegant way, since it does not call for extra code littered in the main code. It restores the state of the system to a graceful recovery. A separate clean up stack is maintained in this method. The resource item and cleanup functions are pushed onto the stack. For recovery they are popped and clean up function executed.

Printf related
How to print a byte in hexadecimal
char c[4]={0xaa,0xbb,0xcc,0xdd}; printf("\n %x \n",(unsigned char)c[1]);

Good coding Practices(Ritchie)


Specifying constants
use const for constants or enum for grouped constants instead of #define

like this const char KI_T0HI= 0xFD ;

Function Names Good Practice


Use Active Names for Functions Like getTime();

Software Design Elements


Data Structures Interfaces Information hiding Resource Management Error Handling

Potrebbero piacerti anche