THE C PROGRAMMING LANGUAGE
[TOC]
Key Points
- Variable is the alias of the RAM address.
- Array of pointer:
int*[8] a
(Should be like this); 👉int *a[8]
(Reality in C)
Forgotten Points:
- Size of different types: 2/4/8(integer), 4/8/16(float-point)
- Some special literals
- Storage class:
auto
,register
,extern
,static
; controlling the visibility and storage of the variables - Pointer variable size is 8 bytes
- Bit field in
struct
: size is the largest type - Type
union
: last assigned - Input/Output Functions:
putchar/getchar
,puts/gets
,printf/scanf
- File IO Functions:
fopen/fclose
,fputc/fputs/fscanf
,fgetc/fgets/fprintf
- Memory Allocation Functions:
calloc/malloc/realloc
Types, Values, and Variables
Types
None Type(For function parameter, function return, and pointer):
void
: 1
Character:
char
/unsigned char
: 1
Integer:
short
/unsigned short
: 2int
/unsigned int
: 4long
/unsigned long
: 8
Floating Point:
float
: 4double
: 8long double
: 16
#include <stdio.h>
#include <limits.h>
int main() {
printf("Storage size: %d \n", sizeof(double));
return 0;
}
Values
Special literals:
Integers Literals:
0213 /* octal */ 0x4b /* hexadecimal */ 30u /* unsigned int */ 30l /* long */ 30ul /* unsigned long */
Floating-point Literals:
314159E-5L /* Legal */
Character Constants:
'x' '\t' '\u02C0'
String Literals:
"hello, \ dear" "hello, " "d" "ear"
Variables
When a local variable is defined, it is not initialized by the system, you must initialize it yourself. Global variables are initialized automatically by the system: int, float, double
(0); char
('\0'
); pointer(NULL
).
Constants
#DEFINE PI 3.1415926
const int a = 1;
Storage Classes
A storage class defines the scope (visibility) and life-time of variables and/or functions within a C Program.
auto int month;
: default storage class for all local variablesregister int miles;
:- 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 (usually one word) and can't have the unary '&' operator applied to it (as it does not have a memory location);
- should only be used for variables that require quick access such as counters;
- should also be noted that defining 'register' does not mean that the variable will be stored in a register. It means that it MIGHT be stored in a register depending on hardware and implementation restrictions.
static int count = 5;
- 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.
extern void write_extern();
,extern int count;
- is used to declare a global variable or function in another file;
- to give a reference of a global variable that is visible to ALL the program files;
- When you use 'extern', the variable cannot be initialized.
Special Types
Pointer
int var = 20; /* actual variable declaration */
int *p_var; /* pointer variable declaration */
p_var = &var; /* store address of var in pointer variable*/
/* address of variable */
printf("Address of var variable: %x\n", &var );
/* address stored in pointer variable */
printf("Address stored in ip variable: %x\n", ip );
/* access the value using the pointer */
printf("Value of *ip variable: %d\n", *ip );
Size of pointer is 8:
int a = 1;
int *p = &a;
printf("Address: %x \n", p); /* Address: e30ee768 */
printf("Storage size: %d \n", sizeof(int*)); /* Storage size: 8 */
Better to assign unused pointer to NULL
:
int *ptr = NULL;
printf("The value of ptr is : %x\n", ptr );
/* The value of ptr is 0 */
if(ptr) /* succeeds if p is not null */
if(!ptr) /* succeeds if p is null */
If function returns pointer, it should be declared with static
storage class.
int * getRandom( ) {
static int r[10];
// ...
return r;
}
Arrays of pointers:
int *ptr[MAX]; // An array of int pointer <=> (int*)[MAX] ptr
char *names[] = { // <=> (char*)[MAX] ptr
"Zara Ali",
"Hina Ali",
"Nuha Ali",
"Sara Ali"
};
Strings
char greeting[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
char greeting[] = "Hello";
#include <string.h>
char str1[12] = "Hello";
char str2[12] = "World";
char str3[12];
strcpy(str3, str1); // str3 <= str1
strcat( str1, str2); // str1 <= str1 + str2
int len = strlen(str1);
Typedef
typedef struct Books {
char title[50];
char author[50];
char subject[100];
int book_id;
} Book;
Built-In Data Structures
Array
double balance[5] = {1000.0, 2.0, 3.4, 7.0, 50.0};
double balance[] = {1000.0, 2.0, 3.4, 7.0, 50.0};
int a[3][4] = {
{0, 1, 2, 3} , /* initializers for row indexed by 0 */
{4, 5, 6, 7} , /* initializers for row indexed by 1 */
{8, 9, 10, 11} /* initializers for row indexed by 2 */
};
int a[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};
Struct
struct Books {
char title[50];
char author[50];
char subject[100];
int book_id;
} book;
struct Books Book1; /* Declare Book1 of type Book */
strcpy( Book1.title, "C Programming");
strcpy( Book1.author, "Nuha Ali");
strcpy( Book1.subject, "C Programming Tutorial");
Book1.book_id = 6495407;
To access any member of a structure, we use the member access operator (.).
Structures as function arguments:
void printBook( struct Books book ) {
printf( "Book title : %s\n", book.title);
printf( "Book author : %s\n", book.author);
printf( "Book subject : %s\n", book.subject);
printf( "Book book_id : %d\n", book.book_id);
}
Pointers to structure:
struct Books *struct_pointer;
struct_pointer = &Book1;
struct_pointer->title;
Bit Fields
struct packed_struct {
unsigned int f1:1;
unsigned int f2:1;
unsigned int f3:1;
unsigned int f4:1;
unsigned int type:4;
unsigned int my_int:9;
} pack;
Note that:
- C automatically packs the above bit fields as compactly as possible
pack
takes up 4 bytes (the size of the firstint
), as the maximum possible size that the values could take is 3 bytes(8 + 9 bits).
Union
- store different data types in the same memory location;
- only one member can contain a value at any given time;
- an efficient way of using the same memory location for multiple-purpose.
union Data {
int i;
float f;
char str[20];
} data;
- The memory occupied by a union will be large enough to hold the largest member of the union.
- In the above example, data type will occupy 20 bytes of memory space.
#include <stdio.h>
#include <string.h>
union Data {
int i;
float f;
char str[20];
};
int main( ) {
union Data data;
printf( "Memory size occupied by data : %d\n", sizeof(data)); /* Memory size occupied by data : 20 */
return 0;
}
- When assigning multiple types, the values got corrupted because they all take the the same memory space.
- The last assigned type is the final type:
union Data data;
data.i = 10;
data.f = 220.5;
strcpy( data.str, "C Programming");
printf( "data.i : %d\n", data.i);
printf( "data.f : %f\n", data.f);
printf( "data.str : %s\n", data.str);
/* data.i : 1917853763
data.f : 4122360580327794860452759994368.000000
data.str : C Programming */
Functions
Everything is pass by value!
E.g. structs, pointers, ...
Input & Output
int getchar(void)
, int putchar(int c)
:
#include <stdio.h>
int c;
printf( "Enter a value :");
c = getchar( );
printf( "\nYou entered: ");
putchar( c );
char *gets(char *s)
, int puts(const char *s)
:
#include <stdio.h>
char str[100];
printf( "Enter a value :");
gets( str );
printf( "\nYou entered: ");
puts( str );
int scanf(const char *format, addresses...)
, int printf(const char *format, variables, variables)
:
#include <stdio.h>
char str[100];
int i;
printf( "Enter a value :");
scanf("%s %d", str, &i);
printf( "\nYou entered: %s %d ", str, i);
File IO
- Open:
FILE *fopen( const char * filename, const char * mode )
int fclose( FILE *fp )
- Write:
int fputc( int c, FILE *fp )
int fputs( const char *s, FILE *fp )
int fprintf(FILE *fp,const char *format, ...)
- Read:
int fgetc( FILE *fp )
char *fgets( char *buf, int n, FILE *fp )
int fscanf(FILE *fp, const char *format, ...)
: stops reading after encountering the first space character
#include <stdio.h>
FILE *fp;
fp = fopen("/tmp/test.txt", "w+");
fprintf(fp, "This is testing for fprintf...\n");
fputs("This is testing for fputs...\n", fp);
fclose(fp);
Command-Line Arguments
#include <stdio.h>
int main( int argc, char *argv[] ) {
if( argc == 2 ) {
printf("The argument supplied is %s\n", argv[1]);
}
else if( argc > 2 ) {
printf("Too many arguments supplied.\n");
}
else {
printf("One argument expected.\n");
}
}
Preprocessors
#include
#define
#undef
#ifdef MACRO // Returns true if this macro is defined.
#ifndef MACRO // Returns true if this macro is not defined.
#if
#else
#elif
#endif // Ends preprocessor conditional.
#error
#pragma
Usage:
#ifndef MESSAGE
#define MESSAGE "You wish!"
#endif
#define message_for(a, b) \
printf(#a " and " #b ": We love you!\n")
#if SYSTEM_1
# include "system_1.h"
#elif SYSTEM_2
# include "system_2.h"
#endif
Predefined Macros:
#include <stdio.h>
printf("File: %s\n", __FILE__ );
printf("Date: %s\n", __DATE__ );
printf("Time: %s\n", __TIME__ );
printf("Line: %d\n", __LINE__ );
printf("ANSI: %d\n", __STDC__ ); // 1 when compiled with ANSI standard
Errors
Use
stderr
file stream to output all the errors.<stdlib.h>
:EXIT_SUCCESS = 0
;EXIT_FAILURE = -1
.
#include <stdio.h>
#include <stdlib.h>
main() {
int dividend = 20;
int divisor = 5;
int quotient;
if( divisor == 0) {
fprintf(stderr, "Division by zero! Exiting...\n");
exit(EXIT_FAILURE);
}
quotient = dividend / divisor;
fprintf(stderr, "Value of quotient : %d\n", quotient );
exit(EXIT_SUCCESS);
}
Memory Allocation
- Allocate:
void *calloc(int num, int size)
: an array of num elements each of which size in bytes will be size; values are initialized as 0void *malloc(int num)
: an array of num bytes; values are not initializedvoid *realloc(void *address, int newsize)
- Free:
void free(void *address)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* allocate memory dynamically */
char *description;
description = malloc( 200 * sizeof(char) );
description = calloc(200, sizeof(char));
if( description == NULL ) {
fprintf(stderr, "Error - unable to allocate required memory\n");
} else {
strcpy( description, "Zara ali a DPS student in class 10th");
}
printf("Description: %s\n", description );
/* release memory using free() function */
free(description);