Download as ppt, pdf, or txt
Download as ppt, pdf, or txt
You are on page 1of 57

Tips and tricks

 Primitive
 Non primitive
 char 1
 int compiler specific
 long 4
 float 4
 double 8 main(){
 long double 10 long l;
long double ld;
printf("%d %d", sizeof(long),
short
sizeof(ld)); //4 sizeof(long)
short int si;
//sizeof(long double) 10
short si;
//4 10
long }
long int li;
long li;
 English alphabets
 Digits 0-9
 Special character
 White space
 Escape sequences ‘\n’
 Trigraphs
??( [ ??< { ??= #
??) ] ??< } ??/ \
??! | ??’ ^ ??- ~

printf(“Delete file (are you really sure??): “ ) ;


 Naming purpose
1. Start with letter / _ followed letter / digit / _
2. Not keyword
3. Cannot a special character @ #
4. 8 Characters

abc
_abc
1abc
123
_123
__aa
auto
a_1
__aa
int
#include<stdio.h>
int integer = 5;
char character = ‘5’;
char *string = “5”;
main(){
printf(“%d %d %d”, string, character, integer);
printf(“%s %c %c”, string, character, integer);
printf(“%d”, (‘5’ > 5));
{
int x = -2;
unsigned int ux = -2;

printf(“%o %o”, x, ux);


printf(“%d %d”, x/ 2, ux / 2);
printf(“%o %o”, x >> 1, ux >> 1);
printf(“%d %d”, x >> 1, ux >> 1);
}
}
 const keyword
int const a;
const int a;
int const *pci;
pci is a pointer to a constant integer. You can change the pointer’s value but not the value
to which it point.

int *const cpi;


Which is a constant pointer to integer. Here the pointer is the constant;

int const *const cpci;


Both the pointer and value are constant

 Named constant
#define MAX_ELEMENTS 50

 Value constant
 Area in the program where the identifier is
accessible.
 Scope of local variable in factions
 No other function may access these variables by their
names, because these names are not valid outside the
function
 It is legal to declare different variables with the same
names so long as they are not declared in the same scope.
 Type of Scopes
 File scope
 Function scope
 Block scope
 Prototype scope
int a;
int b(int c);
int d(int e)
{
int f;
int g(int h);

{
int f, g,I;

}
{
int I;

}
}
 A list of statements enclosed in braces is called a block.
 Any identifiers declared at the beginning of a block
have block scope.
 If an identifier in a nested block has the same name as
one in any outer block, then the inner definition hides
the outer one.
 Variables declared in each block are inaccessible from
other block because their scope does not overlap.
 In K&R C, the scope of formal parameters to a function
began at the declaration of the parameters, which was
outside the body of the function.
 ANSI C prevents this error from happening by giving
the formal parameter block scope in function’s
outermost block.
 File scope
 Any identifier declared outside of all blocks has file scope,
meaning that the identifier may be accessed anywhere from its
declaration to the end of the source file in which it was
declared.
 Declaration written in a header file that is then #include’d into
another file are treated as if they were written directly in the
including file; their scope is not limited by the end of the
header file.
 Prototype scope
 Prototype scope applies only to argument names declared in
function prototypes.
 Function Scope
 It applies only to statement labels which are used with goto
statements. Basically, function scope boils down to a simple
rule – all statement labels in a function must be unique.
 The linkage of an identifier determines how multiple
occurrence of the identifiers are treat. The scope of an
identifier is related to its linkage, but the two
properties are not same.
 There are tow types of linkage - external, internal and
none. Identifiers that have no linkage are always
individuals, that is, multiple declarations of the
identifier are always treated as separate and distinct
entities.
 Internal linkage means that all declarations of the identifier
within one source file refers to a single entity, but declarations
of the same identifier in other source files refer to different
entity.
 All the references to an identifier with external linkage refer to
the same entity.
typedef char *a;
int b;
int c(int d)
{
int e;
int f(int g);

}
 By default the linkage of identifiers b, c and f is
external.
 The remaining identifier has no linkage.
 Something that normally has external linkage, the
keyword static gives it internal linkage.
 static int b;
 static int c(int d);
 extern keyword, in general, specifies external
linkage for an identifier and is used to get access to
an entity that is defined elsewhere.
static int i;
int func()
{
int j;
external int k;
external int I;

}
 The storage class of a variable refers to the type of memory in
which the variable’s value is stored.
 The storage class of a variable determines when it is created
and destroyed and how long it will retains its value.
 Storage
 In ordinary memory
 Stack
 Hardware register
 Variables declared outside of any blocks are always stored
in static memory, that is, in memory that is not stack.
 There is no way to specify any other storage class for them.
 Static variables are created before the program begins to run
and exist throughout its entire execution. They retain
whatever value they are assigned until a different value is
assigned or until the program complete.
 The default storage class for variables declared within a block is
automatic, that is, on the stack.
 Keyword auto.
 are created just before the program execution enters the block in
which they are declared, and discarded just as execution leaves
that block.
 Within block keyword static changes the storage class from
automatic to static.
 Variables with static storage class exist for the entire duration of
the program, rather just the duration of the block in which it is
declared.
 The formal parameters to a function cannot be declared as static,
because argument are always passed on the stack to support
recursion.
 The register keyword may be used on declarations of automatic
variables to indicate that they should be stored in the machine’s
hardware register than memory.
 The compiler is free to ignore the register keyword.
 You want to declare the variables that are used most heavily an
register variable.
 Do not use & operator with a register variable.
int i = 1;
main(){
int i = 2;
printf("%d", i);
{
int i = 3;
printf("%d", i);
{
i = i + 1;
printf("%d", i);
}
}
printf("%d", i); next(){
} static int i = 0;
printf("%d", ++i); 0123
}

main(){
next();
next();
next();
}
Operators
Precidence
Associativity

1. Primary: ( ) [] . -> (L-R)


2. Unary: ! ~ + - * & (type) sizeof() (R-L)
3. Multiplicative: * / % (L-R)
4. Additive: + - (L-R)
5. Shift: << >> (L-R)
6. Relational: < > <= >= (1 / 0) (L-R)
7. Equality: == != (1 / 0) (L-R)
8. Bitwise: & (L-R)
9. Bitwise: ^ (L-R)
10.Bitwise: | (L-R)
11.Logical: && (L-R)
12.Logical: || (L-R)
13.Assignment: = += -= *= (R-L)
14.Conditional: (R-L)
15:Comma: , (L-R)
 Widening
int i = 10;
float f = i;
 Narrowing
float f = 3.14;
int i = f;
 Casting
float f = 3.14;
int I = (float)f;
main(){
double d;
float f;
long l;
int i;
i = l = f = d = 100 / 3; printf(“%g %g %g %g”, I, l, f, d);
d = f = l = i = 100 / 3; printf(“%g %g %g %g”, I, l, f, d);
i = l = f = d = 100 / 3.; printf(“%g %g %g %g”, I, l, f, d);
d = f = l = i = (float)100/3; printf(“%g %g %g %g”, I, l, f, d);
}

main(){
double d = 3.2, x;
int i = 2, y;
x = (y = d / i) * 2; printf(“%d %d”, x, y);
y = (x = d / i) * 2; printf(“%d %d”, x, y);
y = d * (x = 2.5 / d); printf(“%d”, y);
x = d * (y = ((int)2.9 + 1.1) / d); printf(“%d %d”, x, y);
}
1. x = (-3) + 4 * 5 - 6;

2. x = 3 + 4 % 5 - 6;

3. x = -3 * 4 % -6 / 5;

4. x = (7 + 6) % 5 / 2;
int x = 2, y, z;

1. x *= 3 + 2;

2. x *= y = z = 4;

3. x = y == z;

4. x == (y = z);
int x, y, z, k;
x = 2; y = 1; z = 0;

1. k = (x && y) || z;

2. k = x || ((!y) && z); //1

3. k = x || !y && z;

int x, y;
x = y = 1;
1. z = x++ - 1;

2. z += -x++ + ++y;

3. z += -x+++++y;

4. z = x / ++x;
int x = 1;

1. k = (!x) | x;

2. k = x ^ x;

3. k = x | ~x;

int x, y, z, k;
x = 03; y = 02; z = 01;

1. k = x | (y & z);

2. k = x | y & ~z;

3. k = x ^ y & ~z;

4. k = x & y && z;
main(){
int x = 1, y = 1, z = 1;

x += y += z;
printf(“%d”, x < y ? y : x);

printf(“%d”, x < y ? x++ : y++);


printf(“%d %d”, x, y);

printf(“%d”, z += x < y ? x++ : y++);


printf(“%d %d”,y, z);

x = 3; y = z = 4;
printf(“%d”, (z >= y >= x) ? 1 : 0);
printf(“%d”, (z >= y && y >= x));
}
main(){ if(z = (y == 0)) x = 5;
int x, y = 1, z; x = 3;
if(y != 0) x = 5; printf(“%d %d”, x, z);
printf(“%d”, x);
if(x = y= z); x = 3;
if(y == 0) x = 3; printf(“%d %d”, x, z);
else x = 5; }
printf(“%d”, x);

x = 1;
if(y < 0) if(y > 0) x = 3;
else x = 5;
printf(“%d”, x);

if(z = y < 0) x = 3;
else if(y == 0) x = 5;
else x = 7;
printf(“%d %d”, x, z);
main(){ for(y = 1; y < 10; y++) x = y;
int x, y, z; printf(“%d %d”, x, y);

x = y = 0; for(y = 1; (x = y) < 10; y++)


while(y < 10) ++y; x += y; printf(“%d %d”, x, y);
printf(“%d %d”, x, y);
for(x = 0, y = 1000; y > 1; x++, y /= 10)
x = y= 0; printf(“%d”, x,y);
while(y < 10) x += ++y;
printf(“%d %d”, x, y);

y = 1;
while(y < 10){
x = y++;
z = ++y;
}
printf(“%d %d %d”, x, y, z);
char input[] = “SSSWILTECH1\1\11W\1WALLMP1”;
main(){
int i, c;
for(i= 2; (c = input[i] )!= ‘\0’; i++){
switch(c){
case ‘a’: putchar(‘i’); continue;
case ‘1’: break;
case 1: while((c = input[++i]) != ‘\1’ && c != ‘\0’);
case 9: putchar(‘S’);
case ‘E’:
case ‘L’: continue;
default: putchar(c);
continue;
}
putchar(‘ ‘);
}
putchar(‘\n’);
}
main(){
int x, y, z;

x = y = z = 1;
++x || ++y || ++z; printf(“%d %d %d”, x, y, z);

x = y = z = 1;
++x && ++y || ++z; printf(“%d %d %d”, x, y, z);

x = y = z = 1;
++x && ++y && ++z; printf(“%d %d %d”, x, y, z);

x = y = z = -1;
++x && ++y || ++z; printf(“%d %d %d”, x, y, z);

x = y = z = -1;
++x || ++y && ++z; printf(“%d %d %d”, x, y, z);

x = y = z = -1;
++x && ++y && ++z; printf(“%d %d %d”, x, y, z);
}
 An L-value is something that can appear on the left side of equal
sign.
 An R-value is something that can appear on the right side.
 a = b + 25;
 A is a L-value it identifies a place where a result can be stored, b +
25 is an R-value because it contains a value.
 b + 25 = a;
 a, can also be used as an R-value because every place contains a
value. However, b + 25 cannot be used as a L-value because it
does not identify a specific place. That the assignment is illegal.

int a[30]; int a, *pi;


… …
a[b + 10] = 0; pi = &a;
*pi = 20;
 Memory & Addresses
 Issues
 It is machine-dependent whether the address of a word is
the address of the leftmost byte in the word or the
rightmost.
 Boundary alignment is another hardware issue. On
machine with these requirement, integers can only begin
with certain bytes, usually those whose addresses are
multiple of 2 or 4.
 Each memory location is identified by a unique
address.
 Each location in memory contains a value.
 The process of following a pointer to the location to
which it points is called indirection or dereferencing the
pointer.
 Unary *
a b c d e
112 -1 3.14 100 108

int a = 112, b = -1;


float c = 3.14;
int *d = &a;
float *e = &c;
 Thus the E-value of *d is 112 – the content of the
location 100. The L-value would be location 100 itself.
char *c;
double *d;
printf(“%d %d”, sizeof(c), sizeof(*c));
printf(“%d %d”, sizeof(d), sizeof(*d));

int i = 10;
int *p = i;
int *p = &i;
Uninitialized and Illegal Pointers
int *a;

*a = 12;
The NULL pointer
What happens if the indirection is performed on a Null pointer?
The result is implementation dependent. On some machine, the indirection access the memory
location zero. The compiler ensures that there aren’t any variable stored at location zero, but
machine does not prevent you from accessing and modifying the location.
On other machines, indirection on a NULL pointer causes a fault that terminates the program.
 What about *&a = 25;
 What about *100 = 25;
 100 is integer in type. Convert “integer” to “pointer to integer”.
 *(int *)100 = 25;
 Arithmetic Operations
 Pointer + or – integer
 Pointer – Pointer
 Relational Operations
 < <= > =>
 The stdarg Macro (stdarg.h)
 va_list (Datatype)
 va_start (Macro)
 va_arg (Macro)
 va_end (Macro)

#include<stdarg.h>
Float average(int n_values, …){
va_list var_arg;
int count;
float sum = 0;

va_start(var_arg, n_values);

for(count = 0; count < n_values; count++){


sum += va_arg(var_arg, int);
}

va_end(var_arg);
return sum / n_values;
}
avg1 = average(3, x, y, z);
int a[] = {0, 1, 2, 3, 4};
main(){
int I, *p;
for(i = 0; i <= 4; i++) printf(“%d “, a[i]);

for(p = &a[0]; p <= &a[4]; p++) printf(“%d “, *p);

for(p = &a[0], i = 1; i <= 5; i++) printf(“%d “, *p);

for(p = a, i = 0; p + I <= a + 4; p++, i++) printf(“%d “, *(p + i));

for(p = a + 4; p >= a; p--) printf(“%d ”, *p);

for(p = a + 4, i = 0; i <= 4; i++) printf(“%d”, p[-i]);

for(p = a + 4; p >= a; p--) printf(“%d ”, a[p – a]);


}
int a[] = {0, 1, 2, 3, 4 };
int *p[] = {a, a + 1, a + 2, a + 3, a + 4 };
int **p = p;
main(){
printf(“%d %d”, a, *a);
printf(“%d %d %d”, p , *p, **p);
printf(“%d %d %d”, pp, *pp, **pp);

pp++; printf(“%d %d %d”, pp - p, *pp - a, **pp);


*pp++; printf(“%d %d %d”, pp - p, *pp - a, **pp);
*++pp; printf(“%d %d %d”, pp - p, *pp - a, **pp);
++*pp; printf(“%d %d %d”, pp - p, *pp - a, **pp);

pp = p;
**pp++; printf(“%d %d %d”, pp - p, *pp - a, **pp);
*++*pp; printf(“%d %d %d”, pp - p, *pp - a, **pp);
++**pp; printf(“%d %d %d”, pp - p, *pp - a, **pp);
}
int a[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
int *pa[3] = {a[0], a[1], a[2]};

main(){
int i;
for(i = 0; i < 3; i++)
printf(“%d %d %d”, a[i][2 – i], *a[i], *(*(a + i) + i));

for(i = 0; i < 3; i++)


printf(“%d %d”, *pa[i], p[i]);

}
unsigned int i;
struct Point{
int x; // 2
typedef unsigned int ui,
int y; // 2
uint;
}p1 = {10, 10};
ui i;
p1.x = ?10
uint i;
p1.y = 10
typedef unsigned int uint, U;
uint i;
U i;
struct Point p2 = {10, 20};
typedef struct Point{
struct Point p3;
int x;
p3.x = 10;
int y;
p3.y = 20;
}POINT;

struct point p1;


POINT p1;
//Anonyms structure

struct {
int x;
int y;
};

struct { typedef struct {


int x; int x;
int y; int y;
}p1; }POINT;

p1.x = 10; POINT p1;


p1.y = 20;

struct p2;
//wrong
struct node{
int info;
struct node* next;
};

typedef struct node{


int info;
NODE* next;
}NODE;
NODE *first;

typedef struct node NODE;


struct node{
int info;
NODE* next;
};
NODE* first;
struct B{
int b;
struct A* a;
};

struct A{
int a;
struct B* b;
};

typedef struct A* APTR;


typedef struct B* BPTR;

struct A{
int a;
BPTR b;
};

struct B{
int b;
APTR a;
};
1. Structure hold array
2. Array hold structure : array of structures
struct student{
struct Point{
int roll; //2
int x;
char name[80]; //80
int y;
}s1 = {1, "Abcd"};
}p[5]= {{1, 1}, {2, 2}};
p[0].x = 1
struct student s2;
p[0].y = 1
s2.roll = 1;
p[1] = {2, 2}
strcpy(s2.name, "Abced");
p[2].x = 0
struct student s3 = {1, {'A', 'b', 'c', 'd', '\0'}};
//sizeof(p) =5 X 4 = 20

struct Point p1[3];

struct Point p3[] = {{10, 10}, {20, 20},


{30, 30}};

//sizeof(p3) = 3 X 4 = 12;

p3[2].x = 30
struct Digit{
int i;
};

struct Digit p1, p2, *pt;

p1.i = 10;
p2 = p1;
p2.i = 20;
p1.i = ?10

pt = &p1; Structure holding pointer


pt->i = 20;
p1.i = ?20
1. Structure as argument of function
2. Structure as return type of function

struct Point makepoint(int x, int y){


struct Point p;
p.x = x;
p.y = y;
return p;
}
struct Point translate(struct Point p1, int tf){
struct Point p2;
p2.x = p1.x + tf;
p2.y = p1.y + tf;
return p2;
}
main(){
struct Point p1 = makepoint(10, 10);
struct Point newP = translate(p1, 2);
}
 A bit field is declared exactly like a structure except
that its members are fields of one or more bits.
 Implementation difficulty of bit fields:
 Whether an int bit field is treated as signed or unsigned.
 The maximum number of bits in a bit field. Many compilers
limits bit field members to the size of an integer, so a bit field
declaration that works on a machine with 32-bit integers may
not work on one that uses 16-bit integer.
 Whether the members in a bit field are allocated from left to
right or from right to left in memory.
 When a declaration specifies two bit fields and the second is
too large to fit in the bits left over from the first, the compiler
may either put the second bit field in the next word of memory
or immediately after the first field, overlapping the boundary
between memory location.
struct CHAR{
unsigned ch : 7;
unsigned font : 6;
unsigned size : 19;
};
struct CHAR ch1;

ch font size
7 6 19

size font ch
19 6 7
union Type{
char c;
int i;
double d;
};

sizeof(union Type); //8

union Type t;

t.i = 1;
t.d = 1.2;
t.c = 'c';
printf("%c", t.i); //c
main(){
static struct S1{
char c[4], *s;
}s1 = {“abc”, “def”};

static struct S2{


char *cp;
struct S1 ss1;
}s2 = {“ghi”, {“jkl”, “mno”}};

printf(“%s %s”, s1.c[0], *s1.s);


printf(“%s %ds, ++s2.cp, ++s2.ss1.s);
}
FILE *fp;
FILE *fopen(char *name, char *mode);

MODE

t, b
r, w, a, r+, w+, a+

Call: fp = fopen(name, mode);

Read / Write in form of char


int getc(FILE *fp);
int putc(FILE *fp);

<stdio.h>
STDIN
STDOUT
STDERR

#define getchar() getc(stdin)


#define putchar() putc((c), stdout)
void filecopy(FILE *ifp, FILE *ofp)
{
int c;

while((c = getc(ifp)) != EOF)


putc(c, ofp);
}

int fclose(FILE *fp);

int fscanf(FILE *fp, char *format, …);


int fprintf(FILE *fp, char *format, … );

Line inout and output

char *fgets(char *line, int maxline, FILE *fp);


int fputs(char *line, FILE *fp);

Read / Write an object

size_t fread(void *ptr, size_t size, size_t n, FILE *stream);


Size_t fwrite(void *ptr, size_t size, size_t n, FILE *stream);
#include <stdio.h>

struct mystruct
{
int i;
char ch;
};

int main(void)
{
FILE *stream;
struct mystruct s;

if ((stream = fopen("TEST.$$$", "wb")) == NULL) /* open file TEST.$$$ */


{
fprintf(stderr, "Cannot open output file.\n");
return 1;
}
s.i = 0;
s.ch = 'A';
fwrite(&s, sizeof(s), 1, stream); /* write struct s to file */
fclose(stream); /* close file */
return 0;
}
int fseek(FILE *stream, long offset, int where);

SEEK_SET 0
SEEK_CUR 1
SEEK_END 2

long ftell(FILE *stream);

void rewind(FILE *stream);


A string is a sequence of zero or more characters followed by a NULL byte.

String functions
size_t strlen(char const *string);
//string length
char *strcpy(char* dst, char const *src);
//copying string
char *strcat(char *dst, char const *src);
//concatenating strings
int strcmp(char const *s1, char const *s2);
//string comparisn
Length-Restricted String function
char *strcpy(char *dst, char const *src, size_t len);
char *strncat(char *dst, char const *src, size_t len);
int strncmp(char const *s1, char const *s2, size_t len);
Basic string Search
char *strchr(char const *str, int ch);
char *strrchr(char const *str, int ch);
Finding Any of Several Charecters
Char *strpbrk(char const *str, char const *group);
Finding a Substring
char *strstr(char const *s1, char const *s2);
Finding String Prefixes
size_t strspn(char const *str, char const *group);
size_t strcspn(char const *str, char const *group);
Finding Tokens
char *strtok(char *str, char const *sep);
Error Message
char *strerror(int error_number);
Character Tranformation
int tolower(int ch);
int toupper(int ch);
Memory Operations
void *memcpy(void *dst, void const *src, size_t length);
void *memmove(void *dst, void const *src, size_t length);
void *memcmp(void *a, void const *b, size_t length);
void *memchr(void *a, int ch, size_t length);
void *memset(void *a, int ch, size_t length);
Why Use Dynamic Allocation ?
•Array like declaration build an artificial limitation into the program, making it
incapable of handling problems larger than the size used in declaration.
•The obvious solution is to make the array even bigger, but the second problem
then becomes even worse. Nearly all of the memory used for huge array is
wasted when the numbers of elements actually required is small.
•The assumption that “the array will never overflow” makes it very tempting to
not to bother implementing it.
Malloc and Free

void *malloc(size_t size);


void free(void *pointer);

Calloc and Realloc

void *calloc(size_t num_elements, size_t element_size);


void *realloc(void *ptr, size_t new_size);
Using Dynamic Allocated Memory
int *pi;

pi = malloc(100);
if(pi == NULL){
printf(“Out of memory \n”);
exit(1);
}

If your goal is to get enough memory for 25 integers, though, here is


a much better technique for obtaining it.
pi = malloc(25 * sizeof(int));
int *pi2, I;

pi2 = pi;
for(i = 0; I < 25; I += 1)
*pi2++ = 0;

int I;

for(I = 0; I < 25; I += 1)
pi[i] = 0;
Common Dynamic Memory Errors
•The most common problem with dynamic memory allocation is forgetting to check
whether the requested memory was allocated.

•The second biggest source of error with it, is going outside of the bounds of memory
that was allocated.

•Different error can occurs when using free. The pointer passed to free must be a pointer
that was obtained from malloc, calloc or realloc. Calling free with a pointer to memory
that was not dynamically allocated can cause the program to terminate either right way
or at some time after. Freeing a portion of memory is not allowed; the whole block must
be freed.

•Finally, you must be careful not to access memory that has been freed.

You might also like