C Tutorial (Harry)
#17 Goto Statement In C
Section titled “#17 Goto Statement In C”#37 Structures In C
Section titled “#37 Structures In C”- In C and C++, the
typedefkeyword is used to give a new name (alias) to an existing data type.(int,char,int*,struct, etc.) - This can improve code readability, simplify complex data types, and make code easier to maintain.
- Syntax
typedef <previous_name> <alias_name>;
typedef for Inbuilt datatype
#include <stdio.h>typedef long long ll // ll : long long
int main(){ typedf unsigned long ul; // ul : unsigned long
ul u1, u2; // unsigned long ll l1, l2; // long long intPtr p = &value; return 0;}typedef for Structure ⭐
typdef struct Student{ int marks; char name[34];}std; // std : struct Student
// Or we could use typedef after declaring struct Student// typedef struct Student std;std s1, s2; // struct Student s1, s2s1.id = 56;s2. id = 89;typedef for Pointer
typedef int* intPtr // intPtr : int*intPtr a, b; // int* a, bint c = 89;a = &c;b = c;#58 C Pre-processor Introduction & Working
Section titled “#58 C Pre-processor Introduction & Working”- Compiler converts textual form of a c program into an executable.
- There are four phases for a C program to become an executable:
1 2 3 4PreProcessing -> Compilation -> Assembly -> Linking ⭐- Pre-Processing : Removal of comments, Expansion of macros, Expansion of include files
- Compilation : Assembly level instructions are generated
- Assembly : make
.oor.exe,printfare not resolved , Assembly Level Instructions are converted to machine code. - Links the function implementations
What is a C Pre-Processor
- C preprocessor comes under action before the actual compilation process.
- C preprocessor is not a part of the c compiler
- It is a text substitution tool
- All preprocessor commands begin with a hash symbol
#
Preprocessor Commands:
#define: Used to define a macro.#include: Include an external header file.#undef: Undefine preprocessor macros.#ifdef: Check if a macro is defined (defined: 1, not defined: 0).#ifndef: Check if a macro is not defined (defined: 0, not defined: 1).#if: If any compile-time condition is true.#elif: Alternative ofif; if not true, then it is checked.#else: Execute if no condition is true.#endif: Ends a conditional preprocessor directive.#pragma: To issue some special commands to the compiler.
Include:
#include <stdio.h>#include <stdlib.h>#include <string.h>#59 #define and #include Preprocessor Directives: C Tutorial In Hindi
Section titled “#59 #define and #include Preprocessor Directives: C Tutorial In Hindi”- The
#includedirective causes the preprocessor to fetch the contents of some other file to be included in the present file - This file may in turn
#includesome other file(s) which may in turn do the same. Most commonly the#inlcudedfiles have a “.h” extension, indicating that they are header files.
#Include
mostly header files have promises i.e. is function prototypes.In C programming there are two common formats for #includes:
#include < headerFiIe.h >// The angle brackets say to look in the standard system directories#include " myFile.h"// The quotation marks say to look in the current directory.
Disk drive full path is allowed, but discouraged since it is not portable:
#include <C:\Program Files\Harry\bhai\somefile.h>→ Discouraged ✅- Uses absolute disk path
- Not portable (will break on other systems / compilers / OS)
#include <sys/file.h>→ Encouraged ❌- Refers to header in system include directories
- Relative & Portable across systems where the header exists
#define
- The
#definedirective is used to “define” preprocessor “variables” - The
#definepreprocessor directive can be used to globally replace a word with a number. - It acts as if an editor did a global search-and-replace edit of the file.
#define PI 3.1411. #define for Debugging
#definedirective can be used for debugging- We can have printing statements that we only want active when debugging.
- We can “protect” them in a “
ifdef” block as follows: ⭐
#define DEBUG#ifdef DEBUG {print statement...}#endif ...#undef DEBUG2. Macros using #define
- We can create macros using
#define - Macros operate much like functions, but because they are expanded in place and are generally faster
#define SQUARE(x) x*xfloat PI = 3.141area = PI * SQUARE (radius);Notes: Macros are resolved at, preprocessing and so faster and efficient than functions.
Use case #include & #define
#Include directive
#include <stdio.h>#include "Tutorial2.c" // contain functionDangling();
int main(){ int *ptr = functionDangling(); // from `Tutorial2.c` file return 0;}#Define directive
# define PI 3.141
int main(){ float var = PI; printf("The value of PI is %f\n", var); // 3.141 return 0;}#define Macros
#define SQUARE(r) r*r
int main(){ int r = 4; printf("The area of this circle is %f\n", PI*SQUARE(r));}#60 Predefined Macros & Other Pre-processor Directives: C Tutorial In Hindi
Section titled “#60 Predefined Macros & Other Pre-processor Directives: C Tutorial In Hindi”- Preprocessor is a kind of automated editor that modifies a copy of the original source code
- The
#includedirective causes the preprocessor to fetch the contents of some other file to be included in the present file - In C programming there are two common formats for
#includes - This file may in turn
#includesome other file(s) which may in turn do the same. - Most commonly the
#includefiles have a “.h” extension, indicating that they are header files. - The
#definedirective is used to “define” preprocessor “variables”
Predefined Macros in C
__DATE__: The current date as character literal in “MMM DD YYYY” format__TIME__: This contains the current time as a character literal in “HH:MM:SS” format.__FILE__: The current filename as a string literal.__LINE__: The current line number as a decimal constant.__STDC__: Define as 1(one) when the compiler complies with the ANSI standard.
int main(){ printf("FILE name is %s\n", __FILE__ ); // tutorial60.c printf("Today's Date is %s\n", __DATE__); // Oct 06 2024 printf("Time Now is %s\n", __TIME__); // 12:16:31 printf("Line No. is %d\n", __LINE__); // 7 printf("ANSI: %d\n", __STDC__); // 1}#47 Dynamic Memory Allocation Malloc Calloc Realloc & Free(): C Tutorial In Hindi ⭐
Section titled “#47 Dynamic Memory Allocation Malloc Calloc Realloc & Free(): C Tutorial In Hindi ⭐”Recap
- A statically allocated variable/array has a fixed size in memory.
- Dynamic Memory Allocation allows the size of a data structure to be changed at runtime.
- Memory assigned to a program is divided into four segments:
- Code
- Global/Static Variables
- Stack
- Heap
Stack
- Example:
int arr[10]; - Example:
int a; - Stores local variables, function calls, function parameters.
- Memory is automatically allocated and freed when functions are called/returned.
Global and Static Variables
- Example:
int g;(global) - Example:
static int s;(static local or file scope) - Lifetime is throughout the execution of the program.
- Stored in Global/Static segment, not on the stack.
Heap
- Used for dynamic memory allocation.
- Example:
int* p = (int*)malloc(10 * sizeof(int)); - Memory must be explicitly freed (
free(p);).
Functions for Dynamic Memory Allocation in C ⭐
Section titled “Functions for Dynamic Memory Allocation in C ⭐”- In Dynamic memory allocation, the memory is allocated at runtime from the heap segment
- We have four functions that help us achieve this task:
malloccallocreallocfree
MALLOC & CALLOC
|--------|int *ptr ------> Heap | |________|- The return value is a void pointer (
void*) to the allocated space - Therefore the void pointer needs to be casted to the appropriate type as per the requirements
- However, if the space is insufficient. allocation of memory fails and it returns a NULL pointer.
C malloc()
-
malloc()stands for memory allocation -
Reserves a block of memory with the given number of bytes
-
Values in allocated memory are uninitialized (garbage values)
-
Syntax:
ptr = (ptr_type*) malloc(size_in_bytes); -
Example (array of 3 integers):
ptr = (int*) malloc(3 * sizeof(int));
C calloc()
-
calloc()stands for contiguous allocation -
Reserves n blocks of memory, each of given size
-
All values in allocated memory are initialized to 0
-
Syntax:
ptr = (ptr_type*) calloc(n, size_in_bytes); -
Example (array of 3 integers):
ptr = (int*) calloc(3, sizeof(int));
C realloc()
-
realloc()stands for reallocation -
Used to resize previously allocated memory (via malloc/calloc)
-
Preserves existing data up to the new size
-
Syntax:
ptr = (ptr_type*) realloc(ptr, new_size_in_bytes); -
Example (resize array to 4 integers):
ptr = (int*) realloc(ptr, 4 * sizeof(int));
void* Pointer
- A
void*is a generic pointer that can point to any data type - Cannot be dereferenced directly without typecasting
- Used in memory allocation functions (
malloc,calloc,realloc)
(int*) Type Cast Operator
- It tells the compiler: “Treat this value as a pointer to int”.
int* p = (int*) malloc(sizeof(int));
mallocreturns avoid*(generic pointer). In C:void*can be assigned to any pointer type without cast.- So this works fine too:
int* p = malloc(sizeof(int)); - Implicit conversion from
void*to other pointers is not allowed. - That’s why we must use
(int*)malloc(...)in C++.
C free()
- fee() is used to free the allocated memory
- If the dynamically allocated memory is not required anymore, we can free it using free function.
- This will free the memory being used by the program in the heap
- Syntax:
free(ptr)
Note: Malloc() vs Calloc()
malloc: Allocates a block of memory but does not initialize the memory. The memory block will contain garbage values.calloc: Allocates memory and initializes all bits to zero. This means all the values in the allocated memory will initially be set to zero.
Example
- We can use dynamic memory allocation to allocate memory during runtime.
- Dynamic memory allocation functions are under
<stdilib.h>file
1. Malloc Use Case
#include <stdio.h>#include <stdlib.h>
int main(){ // Use of malloc int *ptr; int n; printf("Enter the size of the array you want to create\n"); scanf("%d", &n);
ptr = (int *)malloc(n*sizeof(int));
for(int i=0; i<n; i++){ // ptr[i]=*(ptr+i):value at pointer (ptr+i), // &ptr[i]=(ptr+i):address of pointer (ptr+i) printf("Enter the value no %d of this array\n", i); scanf("%d", &ptr[i]); }
for(int i=0; i<n; i++){ print("The value at %d of this array is %d\n", i, ptr[i]); }}Input:Enter the size of the array you want to create3Enter the value no 0 of this array5Enter the value no 1 of this array6Enter the value no 2 of this array7Output ( Memory is allocated at runtime i.e. size `n` ) :The value at 0 of this array is 5The value at 1 of this array is 6The value at 2 of this array is 7// Value at out of bound of pointerprint("The value at ptr[3] is %d\n", ptr[3]); // 12838462834 Garbage Value2. Calloc Use Case
#include <stdio.h>#include <stdlib.h>
int main(){ // Use of calloc int *ptr; int n; printf("Enter the size of the array you want to create\n"); scanf("%d", &n);
ptr = (int *)calloc(n,sizeof(int));
//for(int i=0; i<n; i++){ // print("Enter the value no %d of this array\n", i); // scanf("%d", &ptr[i]); //}
for(int i=0; i<n; i++){ print("The value at %d of this array is %d\n", i, ptr[i]); }}Input:Enter the size of the array you want to create4Output: (If value not Initialised in Calloc, it is set to `0`)The value at 0 of this array is 0The value at 1 of this array is 0The value at 2 of this array is 0The value at 2 of this array is 03. Realloc : Consider Code Connected after the Calloc i.e ptr assigne 4 byte of memory
// Use of callocprintf("Enter the size of the new array you want to create\n");scanf("%d", &n);
ptr = (int *)realloc(ptr,n*sizeof(int));
for(int i=0; i<n; i++){ print("Enter the new value no %d of this array\n", i); scanf("%d", &ptr[i]);}
for(int i=0; i<n; i++){ print("The new value at %d of this array is %d\n", i, ptr[i]);}Input:Enter the size of the new array you want to create\n6Enter the new value no 0 of this array1Enter the new value no 1 of this array2Enter the new value no 2 of this array3Enter the new value no 3 of this array4Enter the new value no 4 of this array5Enter the new value no 5 of this array6Output:The new value at 0 of this array is 1The new value at 1 of this array is 2The new value at 2 of this array is 3The new value at 3 of this array is 4The new value at 4 of this array is 5The new value at 5 of this array is 64. Free
free(ptr); // its a good practice to use free