Module 1 Final
Module 1 Final
MODULE – 01
Chapter-01
1. Introduction to Computing
1.1 Computer languages
Machine Languages
Machine language is the only language that a computer's hardware can directly understand and
execute. All other programming languages, no matter how advanced, must be translated into
machine language for a computer to run the program.
Symbolic Languages
High-Level Languages
They are portable, allowing the same code to run on different computers with minimal
changes.
High-level languages are easier for humans to read and write, using syntax that is closer
to human language.
They must be converted to machine language through a process called compilation,
which is done by a compiler.
Early examples include FORTRAN (for scientific/engineering) and COBOL (for
business). C is another widely used high-level language.
#include <stdio.h>
int main() {
int a = 5, b = 3, sum;
sum = a + b;
printf("Sum = %d\n", sum);
return 0;
}
To write a program, a text editor is used. This can be a simple text editor (like
Notepad), a word processor (saving as plain text), or more commonly, an integrated
development environment (IDE) that combines editing, compiling, and debugging tools. Text
editors allow you to write, modify, and save your source code files (e.g., program.c). Features
like search and replace, cut, copy, and paste commands, and tab settings are helpful for efficient
coding.
Compiling Programs
The compiler is responsible for translating the human-readable C source code into machine
language. This is typically a two-part process:
1. Pre-processor: This initial stage handles directives (like #include <stdio.h>) that modify
the source code before the main compilation.
2. Translator: The main compiler then takes the pre-processed code and translates it into
machine language instructions. The output of the compiler is an object module (e.g.,
[Link] or program.o), which contains the machine language code, but is not yet ready
to run.
Linking Programs
Modern C programs often utilize many pre-written functions provided in libraries. The
linker is a program that takes the object module generated by the compiler and combines it
with these library functions and other object files to create a single, complete executable
program. This executable file contains all the machine code necessary to run the program.
Executing Programs
Once the executable program is created, it is ready for execution. This is handled by an
operating system utility known as the loader. The loader's job is to load the executable file
from secondary memory (like a hard drive) into the computer's main memory (RAM). Once in
RAM, the program takes control, and its instructions are carried out by the central processing
unit (CPU). Program execution often involves user input and display of output on the screen.
System Development Life Cycle (SDLC): The SDLC is a conceptual model that outlines all
the stages involved in the development of an information system. While specific models may
vary, they generally follow a sequence of interdependent phases.
Waterfall Model
The Waterfall model is a traditional, sequential approach where each phase must be completed
before the next begins. It is suitable for projects with clear, stable requirements.
Waterfall model is costly and time-consuming, making it less flexible for changing
requirements.
Agile Model
The Agile model is an iterative and incremental approach that emphasizes flexibility,
collaboration, and rapid delivery of working software. It involves short development cycles
called "sprints" or "iterations."
The Agile model consists of several iterative phases that ensure flexibility and continuous
improvement during software development.
1. Requirement Analysis: This is the initial stage where the development team works to
understand and gather the user’s needs and expectations.
2. Design: Based on the requirements, the architecture and design for the features in the
current iteration are created.
3. Development: The coding and implementation of the planned features are carried out
in this phase.
4. Testing: Quality assurance activities are performed, including bug detection and fixing,
to ensure the developed features work as intended.
5. Deployment: The working software increment is released to customers for use and
feedback.
6. Continued Iterations: The process repeats, with each cycle adding new features or
refining existing ones until the product reaches its final form.
Program Development
This is the most crucial step. Before writing any code, you must thoroughly understand
what the program needs to accomplish.
This involves:
1. Structure charts
2. Pseudocode
3. Flowcharts
Generally, you will use only two of them — a structure chart and either pseudocode or a
flowchart.
Structure Chart
A structure chart, also called a hierarchy chart, is a tool used to show the functional flow of
a program. It breaks the program into logical steps, with each step represented as a separate
module. This design is similar to an architect’s blueprint for a house, as it provides a complete
picture of how the program will be built before coding begins. By carefully laying out the
modules and their interconnections, programmers gain a clear understanding of the system and
avoid mistakes caused by incomplete planning.
Large programs are often complex, consisting of many interrelated parts. The structure chart
helps organize these parts so they are easier to design, understand, and implement. It
distinguishes between the programmer’s product (software, existing inside the computer) and
an engineer’s product (a physical object).
Example: A program to calculate square footage for linoleum and carpeting could be
broken down into modules for getting user info, calculating different areas (kitchen,
bathroom, bedroom, living areas), printing reports, etc.
Pseudocode
Pseudocode is an informal, high-level description of a program's algorithm. It uses a
blend of natural language and programming constructs to outline the logic without adhering to
a specific programming language's syntax.
4.2 total bath area = total bath area + bath length * bath width
4.3 add 1 to baths processed
5 bath cost = total bath area * linoleum price
6 return bath cost
end algorithm Calculate Bathrooms
This pseudocode describes a function to calculate the total cost for linoleum in multiple
bathrooms. It iterates through each bathroom, takes its dimensions, calculates its area, and sums
it up, finally multiplying by the linoleum price.
Flowchart
A flowchart is a graphical representation of an algorithm, using standard symbols to
depict the logical flow of operations, decisions, and data.
This visual diagram shows the same logic as the pseudocode: taking inputs, looping to
calculate area for each bathroom, and returning a final cost.
After designing the program using structure charts, pseudocode, or flowcharts, the next
step is to write the program. Coding should follow the design step by step, usually beginning
at the top of the structure chart and working downward. A well-prepared design makes
programming easier, reduces confusion, and ensures a clear logical flow in the implementation.
Once the program is written, it must be tested to ensure correctness and reliability.
Testing is one of the most important but time-consuming parts of software development. It
validates whether the program works as expected under all possible conditions. The two main
types of testing are blackbox testing, performed by test engineers without knowledge of the
internal code, and whitebox testing, performed by programmers with complete knowledge of
the internal logic.
Blackbox testing checks the system against requirements, treating the program as a
black box where only inputs and outputs are observed. Whitebox testing, on the other hand,
ensures that every line of code, condition, loop, and boundary value is tested at least once. It
also verifies error-handling logic. Together, these methods ensure the program is error-free,
reliable, and meets user requirements.
Chapter-02
An Overview of C
and efficiency. It provides few restrictions, uses block structure and stand-alone functions, and
has a small set of keywords that make coding fast and flexible.
C combines the speed of assembly language with the structured design of higher-level
languages like Pascal or Modula-2. Assembly language is powerful but hard to read, debug,
and maintain, and it is not portable between machines. C solved these problems by offering
structured programming and portability, allowing the same program to run on different
computers easily.
At first, C was mainly used for system programming, such as creating operating
systems, compilers, and utilities. Later, it became popular for all types of programs because it
is fast, efficient, and portable. Even after the invention of C++, C remains widely used—
especially in embedded systems and system-level software—because it is simple, powerful,
and dependable. Thus, C continues to be one of the most important and long-lasting
programming languages in the world.
Language vs Execution:
o A programming language defines what the program is, not how it is executed.
o Execution methods: Compilation or Interpretation.
Interpreter
o Reads and executes code line by line.
o Slower because it processes instructions at run-time.
o Example: Early BASIC worked this way.
o Java: converts code to an intermediate form (bytecode), then interpreted by
JVM.
o Requires interpreter every time the program runs.
Compiler
o Translates the entire program into object code (machine code/binary).
o Once compiled, source code is no longer needed at run-time.
o Compilation is a one-time cost → execution is fast.
o C is designed as a compiled language (though interpreters exist for special
cases).
Speed Difference
o Compiled programs → faster.
Keywords in C
Extended Keywords (compiler-specific, nonstandard): e.g., asm, far, near, huge, pascal,
interrupt.
main() {
// outline of program
f1(); // call to user-defined function
f2();
...
fN();
}
Global declarations
int main(parameter list)
{
statement sequence
}
return-type f1(parameter list)
{
statement sequence
}
return-type f2(parameter list)
{
statement sequence
}...
return-type fN(parameter list)
{
statement sequence
}
Figure 1-1
The general form of a C program
C language provides only keywords → does not directly support I/O, math, graphics,
etc.
Standard Library contains commonly used functions (e.g., printf(), scanf(), sqrt()).
Functions in libraries are reusable building blocks.
When you use a library function:
o Compiler remembers its name.
o Linker connects your code with object code of the library.
Linking:
o Some compilers use their own linker.
o Others rely on the OS linker.
Library functions are in relocatable format:
o Memory addresses are not fixed, only offsets are stored.
o Actual addresses are assigned during linking.
You can also create your own custom libraries.
Note:
o Compiler requires plain text files (not word processor files).
o Compilation & linking process varies with compilers.
o Many compilers provide IDE (Integrated Development Environment) with
built-in editor + compiler.
Chapter-3
Expressions
3.1 The Basic Data types:
In C language, there are some basic data types which are the building blocks for all other
types. C89 defines five of them: char, int, float, double, and void. These are written using
their keywords.
char is used to store characters like letters, numbers, and symbols (usually from the
ASCII set). It always takes 1 byte (8 bits).
int is used to store whole numbers. Its size depends on the system. On old 16-bit
systems, it was 16 bits. On 32-bit systems, it is usually 32 bits. On modern 64-bit
systems, it is also commonly 32 bits. You should not assume its size, because it changes
with compiler and environment.
float is used for decimal numbers with single precision (around 6 digits of accuracy).
double is also for decimal numbers but with double precision (around 15 digits of
accuracy). The range of float and double is very large, at least from 1E–37 to 1E+37.
void means “nothing.” It is used when a function does not return any value, or when
creating a generic pointer (void*) that can point to any type of data.
In C, we can use modifiers with the basic data types (except void) to change their size
or how they handle values. The main modifiers are signed, unsigned, short, and long.
These modifiers help us store numbers more efficiently depending on whether we need
negative values or larger ranges.
The int type can be combined with signed, unsigned, short, and long. For example,
short int uses less memory than a normal int, while long int uses more. Similarly, char can be
either signed or unsigned, which decides whether it can store negative values or only
positive ones. The double type can also be modified with long to give long double (higher
precision). In C99, an extra type called long long int was introduced for very large integers.
By default, if you just write int, it is treated as signed int. So writing signed int is usually
not necessary unless you want to be clear. Also, if you use only a modifier without a type
(like just unsigned), C assumes int. For example, unsigned means unsigned int, and short means
short int.
The difference between signed and unsigned numbers is in how the highest (leftmost)
bit is interpreted. In signed numbers, that bit is the sign flag (0 = positive, 1 = negative).
In unsigned numbers, all bits are used to store the value, so they can hold larger positive
numbers but no negatives. Most systems use the two’s complement method to represent
negative numbers: invert the bits, add 1, and mark the sign bit as 1.
For example, a 16-bit signed integer can hold values from –32,768 to 32,767, but an
unsigned 16-bit integer can hold 0 to 65,535. This means unsigned types give a bigger
positive range, while signed types allow both positive and negative values.
Table 2-1 shows all valid data type combinations supported by C, along with their
minimal ranges and typical bit widths
In C, the names we give to variables, functions, and other items are called identifiers.
An identifier must start with a letter or an underscore (_). After that, you can use
letters, numbers, or underscores. Identifiers are case-sensitive, so count, Count, and COUNT
are all different. You cannot use C keywords (like int, for, while) as identifiers, and you should
avoid using names of library functions.
There are two kinds of identifiers: external (like function names and global variables
that can be used across files) and internal (like local variables inside a function).
The length of identifiers also has limits. In C89, only the first 6 characters of external
identifiers and the first 31 characters of internal identifiers are important. In C99, this increased
to 31 characters for external and 63 for internal identifiers. In C++, up to 1,024 characters are
important.
3.4 Variables:
A variable in C is a named memory location used to store a value that can change while the
program runs. Before using a variable, it must be declared with a data type and optional
modifiers. The general form of declaration is
type variable_list;,
where type is a valid data type and variable_list contains one or more variable names separated
by commas.
For example: int i, j, l;, short int si;, unsigned int ui;, or double balance, profit, loss;. The variable name
does not affect its type.
Variables can be declared in three places: inside a function (local variables), in function
parameters (formal parameters), or outside all functions (global variables).
Local variables:
In C, local variables are variables declared inside a function or a specific block of code, and
they can only be used within that block. These variables are sometimes called automatic
variables because they are created when the block is entered and destroyed when it is
exited. For example, in the two functions below:
void func1(void)
{
int x;
x = 10;
}
void func2(void)
{
int x;
x = -199;
}
The variable x in func1() is completely separate from the x in func2(). Each exists only while
its function is running and cannot affect the other. Local variables are automatically stored on
the stack, and their values are lost once the block ends. To keep a value between function
calls, you can use the static keyword.
Local variables can also be declared inside smaller blocks within a function. For example:
void f(void)
{
int t;
scanf("%d%*c", &t);
if(t == 1) {
char s[80]; // created only when 'if' block executes
printf("Enter name: ");
gets(s);
}
// s is not accessible here
}
Here, s exists only while the if block is running and disappears afterward. Declaring variables
inside the block that uses them helps prevent accidental changes from other parts of the code.
If a variable in an inner block has the same name as one in an outer block, the inner variable
hides the outer one temporarily. For example:
#include <stdio.h>
int main(void) {
int x;
x = 10;
if(x == 10) {
int x; // inner x hides outer x
x = 99;
printf("Inner x: %d\n", x);
}
printf("Outer x: %d\n", x);
return 0;
}
This prints:
Inner x: 99
Outer x: 10
The inner x is a separate variable, and once the block ends, the outer x becomes visible again.
In C89, all local variables must be declared at the start of a block. For example, the following
code causes an error in C89:
void f(void) {
int i;
i = 10;
int j; // error in C89
j = 20;
}
However, in C99 (and C++), you can declare local variables anywhere in a block before their
first use.
Local variables can also be initialized when declared. The value is assigned every time the
block is entered. For example:
#include <stdio.h>
void f(void);
int main(void) {
int i;
for(i = 0; i < 10; i++) f();
return 0;
}
void f(void) {
int j = 10;
printf("%d ", j);
j++; // this change is lost when function exits
}
This prints 10 ten times because j is re-created with the value 10 each time f() is called, and the
increment does not persist outside the function.
In C, when a function needs to use values passed to it, it declares formal parameters to receive
those values. Formal parameters are like local variables inside the function—they exist only
while the function runs and are destroyed when it exits. They are declared inside the
parentheses following the function name. For example:
Here, the function is_in() has two formal parameters: s (a string) and c (a character). The
function returns 1 if c is found in s and 0 otherwise. Although these parameters receive values
from the arguments passed to the function, they behave like normal local variables—you can
assign values to them or use them in expressions. Like all local variables, their content is lost
once the function finishes execution.
Global variables:
In C, global variables are declared outside all functions and can be used anywhere in the
program. They retain their values throughout the program’s execution. For example:
#include <stdio.h>
int count; /* global variable */
void func1(void);
void func2(void);
int main(void) {
count = 100;
func1();
return 0;
}
void func1(void) {
int temp;
temp = count;
func2();
printf("count is %d", count); /* prints 100 */
}
void func2(void) {
int count; /* local variable hides global */
for(count = 1; count < 10; count++)
putchar('.');
}
In this program, the variable count is global and can be used by main() and func1() even though
it is not declared inside them. However, func2() declares a local variable also named count.
Inside func2(), any reference to count refers only to the local variable, leaving the global
variable unchanged. Global variables are stored in a fixed memory area and are useful when
multiple functions need access to the same data. However, overusing global variables can lead
to memory waste and program errors, because changes in one part of the program can affect
other parts unexpectedly. It is generally better to use local variables unless a variable truly
needs to be shared across functions.
1. File Scope – Identifiers declared outside all functions; visible throughout the entire
file (global variables).
2. Block Scope – Identifiers declared inside { } blocks; also includes function
parameters; local to the block.
3. Function Prototype Scope – Identifiers declared in a function prototype; visible only
within that prototype.
4. Function Scope – Labels used with goto; must be within the same function as the goto.
In C, type qualifiers control how variables can be accessed or modified. The two main
qualifiers in C89 are const and volatile (C99 adds restrict).
Const:
A variable declared as const cannot be changed by the program, although it can be initialized
with a value. For example:
Here, a cannot be modified in the program. The const qualifier is also useful in function
parameters to prevent the function from modifying data pointed to by a pointer.
For instance:
#include <stdio.h>
void sp_to_dash(const char *str);
int main(void) {
sp_to_dash("this is a test");
return 0;
}
void sp_to_dash(const char *str) {
while(*str) {
if(*str == ' ') printf("%c", '-');
else printf("%c", *str);
str++;
}
}
In this program, the const ensures that the string cannot be modified inside the function. If you
try to assign to *str, the compiler will produce an error, as shown in the incorrect example:
/* Incorrect version */
void sp_to_dash(const char *str) {
while(*str) {
if(*str == ' ') *str = '-'; // Error: cannot modify const
printf("%c", *str);
str++;
}
}
Many standard library functions, such as strlen(const char *str), also use const to prevent
modification of the input.
The volatile qualifier indicates that a variable’s value may change due to external events (like
hardware or system routines) not visible in the program. This prevents the compiler from
optimizing code in a way that assumes the variable is unchanged. For example:
This declaration ensures that the program cannot modify port (because of const), and the
compiler knows its value may change unexpectedly (because of volatile), preventing unwanted
optimizations or side effects.
auto
void func() {
auto int x = 10; // 'auto' is optional
printf("%d", x);
}
Register
Suggests the compiler to store variable in CPU register for fast access.
Stored in: CPU register (if available)
Scope: Local to the block/function
Lifetime: Only during function execution
Example:
void func() {
register int speed = 100;
printf("%d", speed);
}
Static
Extends the lifetime of a variable to the entire program, but the scope can still be
local.
Stored in: Data segment
Scope: Local to block (if declared inside a function) or global (if outside)
Lifetime: Entire program execution
Example (inside function):
void func() {
static int count = 0; // remembers value between function calls
count++;
printf("%d\n", count);
}
Extern
If you use a global variable before it’s defined in the same file.
If you want to share a global variable between multiple files.
#include <stdio.h>
int main(void) {
extern int first, last; // Declare variables defined later
printf("%d %d\n", first, last);
return 0;
}
// Define global variables
int first = 10, last = 20;
File1.c
// Define global variables
int x, y;
char ch;
int main(void) {
// Use variables
x = 5;
y = 10;
ch = 'A';
}
File2.c
void func1(void) {
x = 123;
}
void func22(void) {
x = y / 10;
}
void func23(void) {
y = 10;
}
Example:
3.9 Constants in C
In C, constants are fixed values that do not change during program execution. They
represent literal values used directly in the code and can belong to any basic data type such
as int, char, float, or double. Constants are also called literals.
Character Constants
A character constant is a single character enclosed within single quotes (' '), such as 'a', '%',
or '5'. C also supports multibyte characters (for example 'xy') and wide characters, used for
large language character sets. Wide characters are defined using a prefix L, for example:
#include <stddef.h>
wchar_t wc;
wc = L'A'; // Wide character constant
Integer constants are numbers without a decimal point, such as 10, -100, or 35000L.
Floating-point constants include a decimal point or are written in scientific notation, like
11.123, 4.34e–3, or 1.0.
By default:
U or u → unsigned integer
L or l → long integer
F or f → float
L or l (after a decimal number) → long double
Examples:
int x = 123;
In C99, you can also use LL or ll for long long integers, e.g., 12345LL.
Examples:
Octal uses digits 0–7, and hexadecimal uses 0–9 and A–F (or a–f) to represent 10–15.
String Constants
printf("This is a test");
In C, there is no separate string data type — strings are handled as arrays of characters
ending with \0 (null character).
Example Program:
#include <stdio.h>
int main(void)
{
printf("\n\tThis is a test.");
return 0;
}
Output:
This is a test.
Explanation: \n moves to a new line, and \t adds a tab space before printing the text.
Code Meaning
\b Backspace
\f Form feed
\n New line
\r Carriage return
\t Horizontal tab
\\ Backslash
\v Vertical tab
\a Alert (beep)
\? Question mark
3.10 Operators
Syntax:
variable_name = expression;
✅ The left side must be a variable (something that can store a value).
✅ The right side can be:
a constant (5)
another variable (x)
or an expression (a + b * 2)
In that case:
C automatically converts the right side (expression) to the type of the left side (variable).
Example:
int x;
float f;
char ch;
ch = x; // int → char
x = f; // float → int
f = ch; // char → float
f = x; // int → float
Line 1 → ch = x;
Example:
If x = 260, then ch = 260 % 256 = 4.
Line 2 → x = f;
Line 3 → f = ch;
Line 4 → f = x;
Example:
#include <stdio.h>
void main() {
int x = 300;
char ch;
float f;
In C, you can assign values to multiple variables in a single line using multiple
assignments. This makes programs shorter and cleaner.
For example, the statement x = y = z = 0; assigns the value 0 to all three variables x, y,
and z.
Here, the assignment is done from right to left — first z gets 0, then y gets the value of
z (which is 0), and finally x gets the value of y (also 0). This method is commonly used in
professional programs when several variables need the same initial value.
C also provides a shorthand method called compound assignment (or shorthand assignment)
to simplify operations that modify a variable’s value. For example, instead of writing x = x +
10;, you can write x += 10;.
The operator += tells the compiler to add 10 to the current value of x and then store the result
back into x. Similarly, x = x - 100; can be written as x -= 100;.
Compound assignment operators exist for all arithmetic and bitwise binary operators, such as
-=, *=, /=, %=, &=, |=, ^=, <<=, and >>=. In general, any expression of the form var = var operator
expression can be rewritten as var operator = expression. These compound assignments make the
code shorter, easier to read, and are widely used in professionally written C programs.
Arithmetic Operators in C
When both operands are integers, division truncates the remainder (cuts off the decimal
part).
Example:
int x = 5, y = 2;
printf("%d", x / y);
Output → 2
(5 divided by 2 is 2.5, but integer division keeps only 2)
Example:
int x = 5, y = 2;
printf("%d", x % y);
Output → 1
(5 divided by 2 leaves remainder 1)
#include <stdio.h>
int main() {
int x, y;
x = 5;
y = 2;
x = 1;
y = 2;
printf("%d %d", x / y, x % y); // prints 0 1
return 0;
}
Unary Minus
Example:
int x = 5;
printf("%d", -x);
Output → -5
In C, the increment (++) and decrement (--) operators are special operators used to increase
or decrease the value of a variable by 1. They make programs shorter and more efficient.
For example, writing x = x + 1; can be simply written as ++x;, and x = x - 1; can be written as --x;.
T
hese operators can be used in two ways — as prefix (before the variable) or postfix (after the
variable).
When used as a prefix, like ++x, the variable is incremented first, and then its updated value is
used in the expression.
When used as a postfix, like x++, the current value of the variable is used first, and then it is
incremented. For example, if x = 10; y = ++x; then both x and y become 11. But if x = 10; y = x++;,
then y becomes 10 while x becomes 11 after the statement. The same logic applies to the
decrement operator (--x and x--).
C compilers handle increment and decrement operations very efficiently, often producing faster
code than equivalent assignment statements. Therefore, it is good practice to use ++ and --
whenever you need to increase or decrease a variable by one.
The precedence of arithmetic operators determines the order in which operations are
performed. The highest precedence is given to ++ and --, followed by the unary minus (-), then
the operators *, /, and %, and finally the lowest precedence goes to + and - (for addition and
subtraction). Operators that are on the same level of precedence are evaluated from left to
right. You can, however, use parentheses ( ) to change the order of evaluation. Parentheses
work in C just as they do in mathematics — the expressions inside them are evaluated first.
In summary, increment (++) and decrement (--) operators are powerful shorthand tools for
increasing or decreasing variable values efficiently, and understanding their prefix/postfix
behavior and precedence rules helps in writing correct and optimized C programs.
In C, relational operators are used to compare two values and define the relationship between
them, while logical operators are used to combine or invert those relationships. These
operators form the basis of decision-making in C programs (such as in if, while, and for
statements).
In C, the concept of true and false is very important: any nonzero value is true, and zero is
false. The result of a relational or logical expression is either 1 (true) or 0 (false).
🔹 Relational Operators
🔹 Logical Operators
| p | q | p && q | p || q | !p |
|---|---|--------|--------|----|
|0|0|0|0|1|
|0|1|0|1|1|
|1|0|0|1|0|
|1|1|1|1|0|
Example Expression:
10 > 5 && !(10 < 9) || 3 <= 4 → evaluates to true (1).
Both relational and logical operators have lower precedence than arithmetic operators. So, in
an expression like 10 > 1 + 12, the addition is done first (1 + 12 = 13), then the comparison (10 >
13), which results in false (0). Parentheses can be used to change the order of evaluation, e.g.,
(10 > 1) + 12 changes the result.
Although C doesn’t have a direct XOR logical operator, it can be created using existing
operators.
#include <stdio.h>
int xor(int a, int b);
int main(void) {
printf("%d", xor(1, 0)); // Output: 1
printf("%d", xor(1, 1)); // Output: 0
printf("%d", xor(0, 1)); // Output: 1
printf("%d", xor(0, 0)); // Output: 0
return 0;
}
int xor(int a, int b) {
return (a || b) && !(a && b);
}
Explanation:
This function performs an exclusive OR (XOR) operation, which returns true only when
exactly one of the operands is true.
Bitwise Operators in C
C also supports bitwise operators, which operate on individual bits of integer data. They are
used in low-level programming, such as hardware control, encryption, and device drivers.
Bitwise operators cannot be used on float or double types.
Operator Action
& Bitwise AND
` `
^ Bitwise Exclusive OR (XOR)
~ One’s Complement (NOT)
<< Shift Left
>> Shift Right
p q p ^ q (XOR)
000
101
011
110
char ch;
ch = read_modem(); // get a character
return (ch & 127); // clears the 8th bit
Bitwise OR (|)
Used to toggle bits — it sets a bit to 1 only when the bits are different.
Example:
127 ^ 120 results in a value where only differing bits are 1.
<< shifts bits left, filling zeros on the right (multiplies by 2).
>> shifts bits right, filling zeros on the left (divides by 2).
Bits shifted out are lost.
#include <stdio.h>
int main(void) {
unsigned int i = 1;
int j;
// Left shifts
for(j = 0; j < 4; j++) {
i = i << 1;
printf("Left shift %d: %d\n", j, i);
}
// Right shifts
for(j = 0; j < 4; j++) {
i = i >> 1;
printf("Right shift %d: %d\n", j, i);
}
return 0;
}
Explanation:
Each left shift multiplies i by 2, and each right shift divides it by 2.
Example:
If you apply ~ twice, the value returns to its original form. This is sometimes used for simple
encryption.
Ternary operator ?
The ternary operator ? : is a conditional operator in C. It is used as a short form of the if–
else statement. It helps make code shorter and cleaner.
🔹 Syntax
🔹 Working
🔹 Example 1
int x = 10;
int y;
if (x > 9)
y = 100;
else
y = 200;
max = (a > b) ? a : b;
Result:
max = 30 (since a > b is false)
🔹 Example 3
int num = 5;
printf("%s", (num % 2 == 0) ? "Even" : "Odd");
Output: Odd
Pointer?
Pointer Operators in C
Example:
char *ch; // ch is not a character, but a pointer to a character
� The data type (like int, char, float) is called the base type of the pointer.
It tells the compiler what kind of data the pointer will point to.
#include <stdio.h>
int main(void)
{
int target, source; // normal integer variables
int *m; // pointer to integer
return 0;
}
Used to find how many bytes a variable or data type occupies in memory.
Helps to make portable programs that can run correctly on different computer
systems.
🔹Syntax
sizeof variable_name
sizeof(type_name)
Example
double f;
printf("%d ", sizeof f);
printf("%d", sizeof(int));
� Explanation:
Suppose:
o sizeof(double) = 8 bytes
o sizeof(int) = 4 bytes
Output:
84
Example:
size_t s;
s = sizeof(int);
printf("%u", s);
#include <stdio.h>
int main(void)
{
int a;
double b;
char c;
return 0;
}
Comma Operator in C
The comma operator (,) allows you to combine multiple expressions into a single
statement. It evaluates each expression from left to [Link] value of the entire
expression is the value of the last expression in the sequence.
🔹Syntax
(expression1, expression2, expression3, ...);
🔹 Example
x = (y = 3, y + 1);
� Step-by-step:
1. y=3 → assigns 3 to y
2. y+1 → evaluates to 4
3. The last expression (y + 1) becomes the value of the whole expression
4. So, x = 4
✅ Final Values:
y=3
x=4
#include <stdio.h>
int main() {
int x, y;
return 0;
}
✅ Output:
ini
Copy code
x = 4, y = 3
Another Example
#include <stdio.h>
int main() {
int a, b, c;
� Step-by-step:
b=2
c=5
b+c=7 → this is the final value assigned to a.
✅ Output:
a=7
Structure is a collection of different data items (like int, float, char) all grouped together under one
name.
Both . (dot) and -> (arrow) are structure member access operators.
They are used to access individual members (fields) of a structure or union.
Example Structure
struct employee {
char name[80];
int age;
float wage;
};
Shortcut Meaning
[ ] and ( ) Operators in C
Parentheses Operator
Example:
✅ Output → X
3.11 Expressions in C
Here a + b * c is an expression.
Order of Evaluation
Example:
x = f1() + f2();
When you mix different data types in one expression, C automatically converts smaller
types to larger ones. This process is called Type Promotion.
Step-by-Step Conversion
1. ch / i →
o ch (char) becomes int
o result = int
2. f*d →
o float × double → result = double
3. f+i→
o int becomes float → result = float
4. Finally:
o int + double → result = double
o double - float → result = double
Order of promotion:
char → int → float → double → long double
Syntax:
(type) expression
� Example:
(float) x / 2 // forces x to be float before division
Without (float), division between integers would cut off fractions.
Program Example
#include <stdio.h>
int main(void) {
int i;
for(i = 1; i <= 5; i++)
printf("%d / 2 = %f\n", i, (float)i / 2);
return 0;
}
✅ Output:
1 / 2 = 0.500000
2 / 2 = 1.000000
3 / 2 = 1.500000
� Example: