0% found this document useful (0 votes)
9 views111 pages

Module4 Notes 2

The document provides an overview of functions in C, detailing their definition, components, and how to declare and use them. It explains concepts such as function arguments, call by value, call by reference, and how arrays are passed to functions. Additionally, it covers command line arguments, the return statement, and includes examples to illustrate these concepts.

Uploaded by

qurrathunnisa.z
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
9 views111 pages

Module4 Notes 2

The document provides an overview of functions in C, detailing their definition, components, and how to declare and use them. It explains concepts such as function arguments, call by value, call by reference, and how arrays are passed to functions. Additionally, it covers command line arguments, the return statement, and includes examples to illustrate these concepts.

Uploaded by

qurrathunnisa.z
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Functions in C

VT
U
AD
Module-4

D
A
1. What is a Function?
• A function is a block of code that performs a specific task.
• Functions are the building blocks of a C program.
• Every action in a C program happens inside a function (e.g., main()).

VT
U
Components

AD
General Form of a Function • ret-type → The data type of the value returned by the
function.

D
ret-type function-name(parameter list) Example: int, float, char, etc.

A
(Note: A function cannot return an array, but can return a
{ pointer to one.)
body of the function • function-name → Any valid identifier.
• parameter list → Variables that receive values from the caller.
} Can be empty.
If empty, we can explicitly write void.
A
D
AD
U
VT
A
D
AD
U
VT
Parameter Declaration Rules

• Each parameter must have its own type.

VT
Correct:

U
AD
f(int i, int k, int j);

D
A
✘ Wrong:

f(int i, k, float j); // k must have a type


Scope of a Function
Scope means "where a variable or piece of code can be
accessed."
• Function Scope
• Each function is an independent block.

VT
• Code inside a function is private to that function.

U
• No other function can access it directly (except through a function

AD
call).

D
• Key Points

A
• You cannot use goto to jump into another function.
• You cannot define a function inside another function (C is not
block-structured).
Function Arguments in C
1. What Are Function Arguments?
A function argument is a value sent to a function when calling it.
The function must declare parameters to receive these values.
Parameter declarations appear inside the parentheses after the function name.
Example
int is_in(char *s, char c)

VT
{

U
while (*s)

AD
if (*s == c) return 1;

D
else s++;

A
return 0;
}
Parameters:
char *s → pointer to a string
char c → a character
• Function checks if character c exists in string s.
A
D
AD
U
VT
A
D
AD
U
VT
A
D
AD
U
VT
A
D
AD
U
VT
A
D
AD
U
VT
A
D
AD
U
VT
A
D
AD
U
VT
A
D
AD
U
VT
A
D
AD
U
VT
A
D
AD
U
VT
A
D
AD
U
VT
A
D
AD
U
VT
A
D
AD
U
VT
A
D
AD
U
VT
A
D
AD
U
VT
A
D
AD
U
VT
Call by Value & Call by Reference in C

1. Introduction
When a function is called in a programming language, the way arguments are

VT
passed to that function can differ. Two common methods are:

U
AD
• Call by Value

D
A
• Call by Reference
C primarily uses call by value, but call by reference can be simulated using
pointers.
A
D
AD
U
VT
Call by Value
Definition
In call by value, a copy of the actual argument’s value is passed to the

VT
function.

U
AD
Key Points

D
A
•The function works only with a copy, not the original variable.
•Any changes made to the parameter do NOT affect the original
argument.
Example :
#include <stdio.h>
int sqr(int x); Explanation
• t has the value 10.
int main(void)
• sqr(t) receives a copy of 10 → stored in parameter x.
{

VT
int t = 10; • Inside sqr(), x becomes 100, but only the local x changes.

U
printf("%d %d", sqr(t), t); • t in main() remains 10.

AD
return 0;

D
}

A
Output

int sqr(int x) 100 10


{
x = x * x;
return x;
}
A
D
AD
U
VT
A
D
AD
U
VT
A
D
AD
U
VT
A
D
AD
U
VT
A
D
AD
U
VT
Call by Reference
Definition
In call by reference, the address of the variable is passed to the
function.

VT
U
Key Points

AD
D
•The function receives a pointer to the argument.

A
•It can directly modify the original variable, since it accesses memory
using the address.
•C achieves call by reference through pointers.
Example:

#include <stdio.h>

void square(int *x);

int main(void)
Explanation
{

VT
int t = 10; • &t sends the address of t.
square(&t); • x is a pointer that points to t.

U
printf("%d", t);

AD
• *x changes the value stored at that address.
return 0;

D
} • So the value of t becomes 100.

A
void square(int *x)
Output
{
*x = (*x) * (*x); 100
}
A
D
AD
U
VT
A
D
AD
U
VT
A
D
AD
U
VT
A
D
AD
U
VT
A
D
AD
U
VT
Calling Functions with Arrays in C

VT
U
AD
D
A
A
D
AD
U
VT
A
D
AD
U
VT
A
D
AD
U
VT
1. How Array Arguments Work in C
Normally in C, function arguments are passed by value (a copy is sent).
But arrays work differently.

VT
When an array is passed to a function:

U
• Its memory address is passed, not a copy.

AD
• The function can change the actual array in the calling function.

D
A
• This is similar to call by reference.
Example:
void func(int a[]) // receives address of array
2. Example: Converting a String to Uppercase
Code:
void print_upper(char *string) {
int t;
for(t = 0; string[t]; t++) {
string[t] = toupper(string[t]); // modifies the array directly
putchar(string[t]);
}

VT
}

U
What happens?

AD
•The function receives the address of the array.

D
•It changes each character to uppercase.

A
•Because it operates on the actual array, the string in main() also changes.
Output:
Enter a string: This is a test.
THIS IS A TEST.
s is now uppercase: THIS IS A TEST.
The string becomes uppercase both inside the function and after returning.
#include <stdio.h>
#include <ctype.h>

void to_uppercase(char str[]) {


int i = 0;
while (str[i] != '\0') {
str[i] = toupper(str[i]);
i++;
}

VT
}

U
AD
int main() {
char s[] = "hello world";

D
A
printf("Original string: %s\n", s);

to_uppercase(s);

printf("Uppercase string: %s\n", s);

return 0;
}
3. How to Prevent the Array from Being Modified

If you don’t want to change the original array, avoid writing back into it.

Example:
void print_upper(char *string) {

VT
int t;
for(t = 0; string[t]; t++)

U
AD
putchar(toupper(string[t])); // only prints, does NOT modify array
}

D
A
Output:
Enter a string: This is a test.
THIS IS A TEST.
s is unchanged: This is a test.
This version only prints uppercase — original string stays the same.
Version 2: Prevent Original Array from Being Modified
(using Call by Value – Copy the String)**

#include <stdio.h>
#include <ctype.h>
#include <string.h>
void to_uppercase_copy(const char source[], char dest[]) {
int i = 0;
while (source[i] != '\0') {
dest[i] = toupper(source[i]);

VT
i++;

U
}

AD
dest[i] = '\0'; // Null-terminate output
}

D
int main() {

A
char original[] = "hello world";
char upper[50];
printf("Original string: %s\n", original);
to_uppercase_copy(original, upper);
printf("Uppercase copy : %s\n", upper);
printf("Original still : %s\n", original);
return 0;
}
4. Example: How gets() Works Internally
The function gets() accepts a string (character array) from the keyboard.
char *xgets(char *s) {
char ch;
int t;

for(t = 0; t < 80; t++) { // read up to 80 characters


ch = getchar();

VT
if(ch == '\n') {

U
s[t] = '\0'; // terminate string

AD
return s;
}

D
else if(ch == '\b' && t > 0) {

A
t--; // handle backspace Key points:
} •Accepts characters one by one and stores them into the array.
else { •Pressing ENTER adds a null terminator \0.
s[t] = ch; // store character in array •Pressing BACKSPACE removes the previous character.
} •Returns the same pointer that was passed in.
} •The function directly modifies the array used in main().
s[79] = '\0';
return s;
}
Command Line Arguments in C

VT
U
AD
Module-4

D
A
In C, the main() function can receive information from the

VT
command line when you run your program. This is useful when you

U
AD
want to give input to the program at the time of execution (not

D
A
using scanf).
A
D
AD
U
VT
1. What are command line arguments?
When you run a program from the terminal, you can type extra words after the program
name.
Example:

VT
name Tom

U
Here:

AD
name → program name

D
A
Tom → command line argument
These extra words are given to the program through two parameters:
int main(int argc, char *argv[])
argv (Argument Vector / Argument Values)
2. Meaning of argc and argv
•It is an array of strings (character pointers).
•Each element stores one argument.
argc (Argument Count)
Think of it like this:
•It stores the number of arguments passed on the
argv[0] → program name
command line.
argv[1] → first argument
•Always at least 1 because the program name counts as

VT
argv[2] → second argument
the first argument.

U
...

AD
Example:
Example:
name Tom

D
A
run Spot run
Here,
Arguments:
•argc = 2
•argv[0] = "run"
• argv[0] = "name"
•argv[1] = "Spot"
• argv[1] = "Tom"
•argv[2] = "run"
Here: argc = 3
3. Simple Example — Greeting Program
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {

VT
if(argc != 2) {

U
printf("You forgot to type your name.\n");

AD
exit(1);

D
A
}
printf("Hello %s", argv[1]);
Usage:
return 0; name Tom
Output:
} Hello Tom
If you forget to type your name:
You forgot to type your name.
4. Rules about command line arguments
• Arguments must be separated using space or tab.
• Characters like commas are NOT separators.
Example:

VT
Herb,Rick,Fred

U
This is one string → because commas are not valid separators.

AD
D
A
Strings with spaces
Some systems allow:
"my file name"
to be passed as one argument.
5. Converting arguments to numbers
All command line arguments are strings.
If you want numbers, convert using:

VT
•atoi() → converts string to int

U
AD
•atof() → converts string to float

D
A
Example:
count = atoi(argv[1]);
A
D
AD
U
VT
A
D
AD
U
VT
A
D
AD
U
VT
A
D
AD
U
VT
A
D
AD
U
VT
A
D
AD
U
VT
A
D
AD
U
VT
A
D
AD
U
VT
The return Statement in C

VT
U
AD
D
A
1️⃣ What does return do?
(a) It stops the function immediately
When return is executed, the function ends.

VT
Control goes back to the place where the function was called.

U
AD
(b) It sends a value back to the caller (optional)

D
Functions with a return type (like int, char *, float, etc.) must return a

A
value.
void functions do not return any value.
2️⃣ Returning From a Function
Method 1: Reaching the closing brace }
Example:
void hello() {
printf("Hello");

VT
} // function automatically returns here

U
AD
Method 2: Using return statement

D
A
Example:
void hello() {
printf("Hello");
return; // ends function early
}
3️⃣ Multiple return Statements
A function can have more than one return for easier logic.
Example:
int find_substr(char *s1, char *s2)

VT
U
{

AD
D
// if substring is found, return position

A
// otherwise return -1
}
4️⃣ Functions Returning Values
A function with a non-void type must return a value in C99/C++.
Example:
int add(int x, int y) {
return x + y;
}

VT
Wrong:

U
int add(int x, int y) {

AD
return; // ERROR in C99 — missing value

D
}

A
You may use the returned value:
z = add(5, 10); // assigned
printf("%d", add(5,10)); // used directly
Or you may ignore it:
add(5, 10); // return value is discarded
5️⃣ Important Rule

A function value cannot appear on the left side of

VT
U
assignment:

AD
D
A
add(2,3) = 10; // INCORRECT
6️⃣ Types of Functions Based on Return Value
(i) Pure computational functions
• Perform calculations and return a result.
• Example: sqrt(), sin(), custom add()

VT
(ii) Functions that return status of an operation

U
• Return success/failure codes.

AD
• Example:

D
fclose(file) returns 0 on success and EOF on failure.

A
(iii) Functions that return nothing (void functions)
• Only perform actions.
• Example:
void print_vertical(char *s);
Functions Returning Pointers
A function may return a pointer:
char *match(char c, char *s) {
while (*s && *s != c) s++;
return s; // returns pointer to matched character

VT
U
OR '\0'

AD
}

D
A
Key points:
•Pointer return type must match the data type.
•Use char * for char pointers, int * for int pointers, etc.
•Use void * only for generic pointers.
Example to Understand
char *p = match('e', "apple");
String: "apple"
Pointer movement:
a → p → p → l → e → '\0'

VT
↑ match found

U
AD
here

D
Returned pointer points to "e".

A
8️⃣ Void Functions
•Declared with void return type.
•Cannot be used in expressions. int x = print_vertical("hello"); // error

•Example:

VT
void print_vertical(char *str) {

U
AD
while (*str)

D
A
printf("%c\n", *str++);
}
What Does main() Return?
Purpose of Return Value
• main() returns an integer to the operating system.
• Indicates whether the program ran successfully or failed.
• return value; is equivalent to calling exit(value);.

VT
Meaning of Return Values

U
AD
Value Meaning

D
0 Successful execution

A
Non-zero Error or abnormal termination

Example
int main() {
// code
return 0; // success
}
If main() Does Not Return a Value
Undefined Behavior
• If main() does not explicitly return a value, the result is technically
undefined.

VT
Compiler Behavior

U
AD
• Most modern C compilers automatically return 0.

D
• But this is not guaranteed → reduces program portability.

A
Good Practice
Always write:
return 0;
Recursion

VT
U
AD
Module - 4

D
A
➤ What is Recursion?
• Recursion means a function calling itself.

• Used when a problem can be defined in terms of a smaller

VT
U
version of itself.

AD
D
• Also called circular definition.

A
Example: Factorial Using Recursion

• Factorial Definition
• Factorial of a number n:

VT
• 𝑛! = 1 × 2 × 3 ×. . .× 𝑛

U
• Example:

AD
3! = 1 × 2 × 3 = 6

D
A
Recursive Version
int factr(int n) {
if(n == 1)
return 1;
return factr(n - 1) * n;
}

VT
How it works

U
AD
•If n = 1, return 1 → Base condition

D
•Otherwise:

A
factr(n) = factr(n−1) * n
Example for n = 2:
•factr(2) → calls factr(1)
•factr(1) returns 1 → 1 × 2 = 2
#include <stdio.h>
int main()
{
// Recursive function to calculate factorial int num, result;
int factr(int n) {
printf("Enter a number: ");
if (n == 1) // Base condition scanf("%d", &num);
return 1;
// Check for valid input

VT
return factr(n - 1) * n; // Recursive call if (num < 1)
{
}

U
printf("Factorial is not defined for numbers less than 1.\n");

AD
return 0;
}

D
A
result = factr(num); // Function call

printf("Factorial of %d = %d\n", num, result);

OUTPUT: return 0;
Enter a number: 5 }
Factorial of 5 = 120
Iterative (non-recursive) Version

int fact(int n)
{
int answer = 1;

VT
for(int i = 1; i <= n; i++)

U
answer = answer * i;

AD
return answer;

D
A
}
This uses a loop instead of recursion.
How Recursive Calls Work (Important Concept)
•Every time a function calls itself:
• A new set of local variables is created on the stack.
• The function starts again from top.

VT
•When a call finishes:

U
AD
• That copy of the variables is removed from the stack.

D
A
• Control returns to the previous call.
This makes recursive calls behave like they expand out (telescope)
and then fold back in.
Advantages of Recursion Disadvantages of Recursion
Makes some algorithms easier and ✘ Slower due to repeated function calls
cleaner ✘ Uses more memory (each call uses stack space)
Useful for: ✘ Too many recursive calls can cause stack overflow

VT
•Algorithms like quicksort ✘ Iterative (loop-based) versions are often more

U
•Problems that naturally fit recursive efficient

AD
thinking

D
A
•Tree and AI algorithms
Some programmers find recursive thinking
easier than writing loops.
FUNCTION PROTOTYPES
What is a Function Prototype?
A function prototype is a declaration of a function before it is used in a
program.

VT
It tells the compiler:

U
AD
•The function name

D
•The return type

A
•The number of parameters
•The types of parameters
Helps the compiler perform strong type checking
Ensures the function is called with correct arguments
Why are Prototypes Needed?
•They were added in C89 (early C did not have them).
•Modern C strongly encourages prototypes.
•C++ requires prototypes.

VT
Benefits of Prototypes

U
AD
•Detects type mismatches

D
A
•Detects wrong number of arguments
•Helps catch errors before they occur
•Makes code easier to understand and maintain
General Syntax of a Function Prototype

return_type function_name(type param1, type param2, ...);

Parameter names are optional but recommended for readability.

VT
U
Example of a Prototype

AD
void sqr_it(int *i); // prototype

D
A
Wrong usage (type mismatch)
int x = 10;
sqr_it(x); // error: expected int*, got int
The prototype helps the compiler detect this error.
Prototype Provided by Function Definition
If a function is defined before it is used, the definition also acts as its
prototype.
Example:
void f(int a, int b) {

VT
printf("%d", a % b);

U
}

AD
int main() {

D
f(10, 3); // OK: definition already seen

A
}
But in large programs, function definitions are often placed in
separate files.
So prototypes are written separately, usually in header files (.h).
Does main() Need a Prototype?
•No, because it is the first function the system calls.
•All other functions should have prototypes.

Important Difference Between C and C++


C++:
int f(); // means function has NO parameters
C:

VT
int f(); // means parameters are NOT specified (old-style)

U
AD
In C, a function that takes no parameters must be written as:

D
int f(void); // correct C prototype for "no parameters"

A
Function Prototypes Help You
Catch errors early
Avoid wrong arguments
Make programs reliable
Write code that is compatible with C++
OLD-STYLE FUNCTION DECLARATIONS

Before prototypes existed, C used old-style declarations.


Example:
double div(); // old-style
This only tells the compiler:
•The return type (double)
Why Old-Style Is Bad
It does not specify the parameter types.

VT
•No information about parameters

U
•Error-prone
Example:

AD
•Not compatible with C++

D
•Not used in modern C programs
double div(); // old-style declaration

A
Old-style syntax:
int main() {
type function_name();
printf("%f", div(10.2, 20.0));
}
double div(double num, double denom) {
return num / denom;
}
STANDARD LIBRARY FUNCTION PROTOTYPES

Every library function (like printf(), scanf(), strlen(), etc.) must


have a prototype.
Prototypes for standard functions come from header files:

VT
•#include <stdio.h> → prototypes for printf(), scanf()

U
•#include <math.h> → sin(), cos(), sqrt()

AD
•#include <string.h> → strcpy(), strlen()

D
A
Headers contain:
[Link] prototypes
[Link] definitions
Variable Length Parameter Lists (var-args)

What is it?
A function can take different numbers of arguments each time it is called.
Example in real C:
printf() is the most common example:

VT
printf("Sum = %d", x+y);

U
printf("%d %d %d", a, b, c);

AD
How to declare a variable-length function?

D
Use three dots ( ... ) at the end of the parameter list.

A
int func(int a, int b, ...);
Requirement:
A variable-argument function must have at least one fixed parameter.
Illegal:
int func(...); // NO fixed parameter → not allowed
The "Implicit int" Rule (Old C Feature)
What is it?
In old C (C89), if you don’t specify a type, C automatically assumed int.
Example (old style):
f(void) { // return type defaults to int
return 0;

VT
} Modern C (C99, C11, C++):

U
Or:

AD
Implicit int is removed
f(a, b) // parameters default to int

D
register a; You must specify all data types.

A
register b;
So always write:
{
register c; // also defaults to int int f(void)
c = a + b; {
return 0;
return c; }
}
Old-Style vs. Modern Function Parameter Declarations
Modern Style (recommended & used today)
float f(int a, int b, char ch) {
// code
}
Old-Style (classic K&R C)

VT
Parameters listed first, types declared separately:

U
AD
float f(a, b, ch)

D
int a, b;

A
char ch;
{
// code
}
The inline Keyword (C99)
What is it?
inline tells the compiler:
“Try to speed up this function by inserting its code directly at
the place it is called.”

VT
Example:

U
inline int square(int x) {

AD
return x * x;

D
A
}
Important:
•inline is only a request, not a guarantee.
•The compiler may ignore it.
A
D
AD
U
VT
FUNCTION POINTERS
• What is a Function Pointer?
• A function also lives in memory.

VT
• The address of a function can be stored in a pointer.

U
• Once stored, the function can be called using the pointer.

AD
• Function pointers allow you to pass a function as an argument to

D
A
another function.
A
D
AD
U
VT
A
D
AD
U
VT
A
D
AD
U
VT
A
D
AD
U
VT
A
D
AD
U
VT
Syntax:

int (*p)(const char *, const char *);

Meaning:

p → pointer

pointing to a function

VT
that takes two const char* arguments

U
AD
and returns int.

D
A
Parentheses around (*p) are required.

Calling a Function Using a Pointer


Both are valid:
(*p)(a, b); // normal function pointer call
p(a, b); // simpler call
#include <stdio.h>
#include <string.h>

void check(char *a, char *b, int (*cmp)(const char *, const char
*));

int main() {
char s1[80], s2[80];
int (*p)(const char *, const char *);

VT
p = strcmp; // assign function address

U
AD
printf("Enter two strings:\n");

D
gets(s1);

A
gets(s2); void check(char *a, char *b, int (*cmp)(const char *, const char *))
{
check(s1, s2, p);
if ((*cmp)(a, b) == 0)
return 0; printf("Equal\n");
} else
printf("Not Equal\n");
}
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
void check(char *a, char *b, int (*cmp)(const char *, const char *));
int compvalues(const char *a, const char *b);
int main(void)
{ void check(char *a, char *b, int (*cmp)(const char *, const char
char s1[80], s2[80]; *))

VT
printf("Enter two values or two strings:\n"); {
if (!(*cmp)(a, b))

U
gets(s1); gets(s2);
printf("Equal");

AD
if (isdigit(*s1)) else
{ printf("Not Equal");

D
printf("Testing values for equality.\n"); }

A
check(s1, s2, compvalues);
} int compvalues(const char *a, const char *b)
else { {
printf("Testing strings for equality.\n"); if (atoi(a) == atoi(b))
check(s1, s2, strcmp); return 0;
else
}
return 1;
return 0; }
}
C’s Dynamic Allocation Functions
1. What is Dynamic Memory Allocation?
In C, dynamic memory allocation allows you to request
memory during program execution, not at compile time.

VT
It is done using functions like malloc(), calloc(), realloc(), and

U
AD
free().

D
A
Function Purpose
malloc() Allocates memory
calloc() Allocates & initializes memory
realloc() Changes size of allocated memory
free() Frees the allocated memory
Using malloc() for Dynamic Arrays
• Sometimes you want to create an array, but the size is known only at
runtime.
• malloc() allows you to allocate memory from the heap.

VT
• Even if memory is allocated using a pointer, you can still use array indexing.

U
Example:

AD
char *s;

D
A
s = (char *) malloc(100);
Here:
s is a pointer
But you can use it like an array: s[0], s[1], …
This makes it easy to create a dynamically allocated array.
Always Check for Successful Allocation
After calling malloc(), always verify that the memory was allocated.
If allocation fails, malloc() returns NULL.
Using a NULL pointer can crash the program.

VT
Example check:

U
AD
if (s == NULL)
{

D
A
printf("Memory allocation failed");
exit(1);
}
Example : Read a string and print it backwards

#include <stdio.h> printf("Enter a string: ");


#include <stdlib.h> gets(s); // (unsafe but used for textbook-style
#include <string.h>
examples)
int main() {
char *s; // Print string backwards

VT
int i;
for (i = strlen(s) - 1; i >= 0; i--) {

U
s = (char *) malloc(80); // allocate memory putchar(s[i]);

AD
}

D
if (!s)

A
{
printf("Memory request failed.\n"); free(s); // release memory
exit(1); return 0;
}
}
Key points:

• s is a dynamically allocated array.

VT
• You can use s[i] like a normal array.

U
AD
D
A
• malloc() must be checked for NULL.

• Always use free() after use.

You might also like