PRINCIPLE OF PROGRAMMING LANGUAGES
1. What is an imperative type of language? Name any two imperative
languages.
An imperative language is a programming language that specifies how a program works by
giving step-by-step instructions. It uses variables, assignment statements, loops, and
conditional statements to change the program state explicitly. Execution follows a defined
sequence of commands. These languages closely match the computer’s hardware model.
Examples of imperative languages are C and Pascal.
2. What is a heterogeneous array?
A heterogeneous array is an array that can store elements of different data types (e.g.,
integers, strings, floats) in the same array. Unlike homogeneous arrays, its elements are not
restricted to one type. This provides significant flexibility but increases implementation
complexity for the language runtime. Such arrays are commonly supported in high-level,
dynamically typed languages like Python.
3. What distinguishes rectangular arrays from jagged arrays?
Rectangular arrays have rows with the exact same number of columns, forming a proper
matrix structure (e.g., a 3 X 4 array). Memory allocation is uniform and contiguous for all
rows. Jagged arrays (or arrays of arrays) have rows with potentially different numbers of
columns; each row is allocated separately and may have a different length. Rectangular
arrays are simpler to manage, while jagged arrays are more memory-efficient when data
structures are sparse or irregular.
4. What is an array slice? Name any two languages supporting it.
An array slice is a contiguous portion of an array selected using a range of indices (e.g.,
from index i to j). It allows multiple elements to be accessed or manipulated in a single
operation, improving code readability and efficiency. Array slicing avoids manual element
access through looping. Languages that natively support array slicing include Python and
Ada.
5. What is data encapsulation in object-oriented programming?
Data encapsulation is an object-oriented concept that bundles data (attributes) and the
methods that operate on that data into a single unit called a class. Crucially, it restricts direct
access to data members using access specifiers (like private), thereby enforcing data
hiding. Encapsulation protects the data's integrity, manages state changes only through
defined methods, and makes programs easier to maintain and modify.
6. What is method overloading?
Method overloading is a feature of object-oriented programming where multiple methods
within the same class share the same name but differ in their parameter lists. The methods
must be distinguishable by the number, type, or order of their parameters. It allows the same
operation (conceptually) to behave differently based on the input values provided, improving
code readability and promoting reusability of function names.
7. What is dynamic binding?
Dynamic binding (or late binding) is the process of linking a method call to its actual method
definition at runtime. It occurs when a derived class overrides a method of its base class.
The specific method to be executed is decided by the object's actual type, not the reference
type, at the moment of the call. Dynamic binding is the essential mechanism that supports
runtime polymorphism and flexibility in object-oriented systems.
8. What are keyword and positional parameters?
Positional parameters are arguments passed to a function based purely on their ordered
position in the function call; the order is strict and must match the formal parameter
declaration. Keyword parameters are arguments passed using the parameter's name,
making the order unimportant during the function call (e.g., func(y=2, x=1)). Keyword
parameters improve code readability, reduce errors, and are supported in languages like
Python and Ada.
9. What is a formal parameter? Give an example.
A formal parameter is a variable declared in the function's definition or header that serves as
a placeholder for the actual values passed during the function call. It receives values from
the calling function and is used within the function body to perform computations. Formal
parameters exist only during the execution of the function.
Example: In the C function header void add(int x, int y), x and y are the formal parameters.
10. Explain malloc() and calloc() functions with an example.
Both malloc() and calloc() are C library functions used for dynamic memory allocation from
the heap.
● malloc() (Memory Allocation) allocates a requested block of memory but does not
initialize it; the memory block contains garbage values.
● calloc() (Contiguous Allocation) allocates memory for an array of specified elements
and initializes all bytes to zero.
The primary difference is initialization.
Example: int *p = malloc(5 * sizeof(int)); allocates 20 bytes (uninitialized). int *q =
calloc(5, sizeof(int)); allocates 20 bytes and sets all bits to 0.
11. Which allocation method is typically faster: stack-based or
heap-based? Why?
Stack-based allocation is typically faster than heap-based allocation. Stack operations
involve simple manipulation of the stack pointer (a single CPU register), which is extremely
fast and automatic upon function entry and exit. Heap allocation, conversely, requires the
language runtime system to manage complex data structures to find, allocate, and track free
memory blocks, leading to significant overhead and possible fragmentation, making it slower.
12. What is the use of strlen() function? Give syntax.
The strlen() function is used to determine the length of a string in C. It calculates the number
of characters in the string, excluding the null character (\0) that terminates the string. The
function is defined in the <string.h> header file.
Syntax: size_t strlen(const char *string_name);
13. Which function is used to join two strings? Give syntax.
The strcat() function (String Concatenation) is used to join or append the contents of a
source string to the end of a destination string in C. It modifies the destination string in place.
It is crucial that the destination array must have sufficient pre-allocated space to hold the
combined resulting string. This function is also defined in the <string.h> header file.
Syntax: char *strcat(char *destination, const char *source);
14. What is a key design issue for character string types?
A key design issue for character string types is the choice between mutability and
immutability. Mutable strings can be modified after they are created (e.g., changing a
character in place or appending a substring), while immutable strings cannot be modified;
any modification results in the creation of a new string object. This choice affects memory
usage, thread safety, and optimization capabilities. Another issue is whether strings are of a
fixed length or a dynamically variable length.
15. What is a side effect?
A side effect occurs when a function, expression, or statement modifies a state outside its
own local scope or execution environment. This typically happens when a routine changes a
global variable or modifies a parameter that was passed by reference. Side effects reduce
the predictability of a program, making the code harder to understand, debug, and maintain,
as execution order can influence outcomes across different parts of the system.
16. Define user-defined ordinal types.
User-defined ordinal types are programmer-defined data types whose values are ordered,
discrete, and countable. Because the values are discrete, they can be easily enumerated
and compared sequentially. The most common example is the enumeration type (enum),
which allows the programmer to assign a set of meaningful names (constants) to represent a
range of integer values. Ordinal types significantly improve code readability and type safety.
17. What is a local referencing environment?
A local referencing environment is the set of all variable names and constants that are
accessible and valid for use within a specific function, subroutine, or block of code during its
execution. This environment typically includes: local variables declared within the block, the
function's formal parameters, and any non-local variables accessible under the
language's scoping rules (e.g., global variables or variables from outer scopes). The
environment exists only during the lifetime of the block's execution.
18. What are generic subroutines?
Generic subroutines (also known as templates or generics) are functions or procedures
written in a way that they can operate correctly on data of different types without having to
be rewritten for each type. The actual data type is specified as a parameter (often indicated
by a placeholder like T) when the subroutine is called or instantiated. They promote high
code reusability, reduce redundancy, and simplify maintenance by allowing a single
algorithm definition (e.g., a sort function) to work across integers, floats, or custom classes.
19. What is an l-value and r-value?
An l-value (left-value) represents a memory location that can be assigned a value and thus
can appear on the left side of an assignment operator (e.g., a variable name or an array
element). An r-value (right-value) represents a specific data value stored in memory or
computed immediately, and thus can appear on the right side of an assignment operator. In
the statement x = 10 + y;, x is the l-value (the location being changed), and 10 + y evaluates
to the r-value (the data being stored).
20. Show IEEE floating-point standard for single and double precision.
The IEEE 754 standard defines the representation of floating-point numbers:
Precision Type Total Bits Sign Bits Exponent Bits Mantissa (Fraction) Bits
Single Precision 32 bits 1 bit 8 bits 23 bits
Double Precision 64 bits 1 bit 11 bits 52 bits
The sign bit determines if the number is positive or negative. The exponent determines the
magnitude (range), and the mantissa determines the precision (number of significant digits).
This standard ensures consistent floating-point arithmetic across different computer
architectures.
21. Explain entry-controlled and exit-controlled loops.
Entry-controlled loops evaluate the loop condition before executing the loop body. If the
condition is false initially, the loop body will not execute even once. Examples include the for
loop and the while loop. They are suitable for tasks where execution must strictly depend on
a precondition.
Exit-controlled loops evaluate the loop condition after executing the loop body. This
structure guarantees that the loop body executes at least one time, regardless of the initial
condition. The most common example is the do-while loop. They are useful for scenarios like
menu-driven programs or user input validation, where code execution must occur once
before checking for continuation.
22. What is heap-based allocation?
Heap-based allocation is a method of dynamic memory allocation where memory is
requested and allocated from a large, unstructured pool of memory known as the heap
during program execution (runtime). This memory is not tied to function calls and persists
until it is explicitly deallocated by the programmer (e.g., using free() in C) or automatically by
a garbage collector. It is used for dynamic data structures like linked lists and objects whose
required size is not known at compile time.
23. Explain the concept of tail recursion with a suitable example.
Tail recursion is a special case of recursion where the recursive call is the very last
operation executed in the function, and its result is immediately returned without any further
computation. This property is significant because it allows compilers or interpreters to
perform Tail Call Optimization (TCO). TCO converts the recursive call into a simple jump
(goto) statement, reusing the current function's stack frame, which eliminates the overhead
of creating new stack frames and prevents stack overflow errors.
Example:
// Tail-recursive function for factorial calculation
int factorial(int n, int result) {
if (n == 0)
return result;
// The recursive call is the last statement, and its result is returned directly
return factorial(n - 1, n * result);
}
24. What are the issues related to initialization and finalization? Explain
how constructors are chosen in various programming languages.
Initialization issues deal with ensuring that every variable or object is given valid initial
values upon creation. Improper or missing initialization leads to unpredictable program
behavior or runtime errors (e.g., accessing uninitialized memory). Finalization issues
involve the orderly release of resources (memory, file handles, network connections) held by
an object when it is destroyed, which is necessary to prevent memory leaks and resource
wastage.
Constructor Choice: Constructors are special methods used for object initialization. In
languages like C++ and Java, constructors are chosen based on the principle of
constructor overloading, where the language matches the number, type, and order of the
arguments supplied during object creation to the corresponding constructor signature in the
class definition. For example, new MyClass(int, String) selects the constructor defined with
those specific parameters.
25. What is short-circuit boolean evaluation? Explain its advantages.
Short-circuit boolean evaluation is a strategy used for logical expressions (especially those
involving AND (&&) or OR (||)) where the execution of the second operand is skipped if the
final result of the expression can be determined solely by evaluating the first operand.
● In an expression like A && B, if A is false, B is skipped because the result must be
false.
● In an expression like A || B, if A is true, B is skipped because the result must be true.
Advantages: It improves program efficiency by avoiding unnecessary computations.
Crucially, it helps prevent runtime errors; for instance, in (x != 0 && y / x),
short-circuiting prevents a division-by-zero error if x is zero.
26. Explain the garbage collection mechanism.
Garbage collection (GC) is an automatic memory management technique used primarily in
high-level languages (like Java, Python, C#) to identify and reclaim memory occupied by
objects that are no longer reachable or in use by the program.
● The Garbage Collector periodically runs in the background, traversing the program's
reference graph to determine which objects are still "live" (referenced directly or
indirectly by a running thread).
● Any object not reachable from the program's root set is deemed "garbage."
● The GC automatically frees the memory associated with these unreachable objects.
This mechanism simplifies programming by removing the need for explicit memory
deallocation, thereby preventing memory leaks and improving program safety and
reliability, though it can introduce momentary performance overhead due to the
cleanup cycle.
27. Explain the implementation of single inheritance with a suitable
example.
Single inheritance is the simplest form of inheritance in object-oriented programming where
a derived class (subclass) inherits properties and methods from only one base class
(superclass). This establishes a clear, linear, parent–child relationship between the classes
and is fundamental to promoting code reusability. The derived class gains access to the
base class's public and protected members.
Implementation Example (Conceptual):
// Base Class (Parent)
class Vehicle {
protected int speed;
public void start() { }
}
// Derived Class (Child)
class Car extends Vehicle {
private int gears;
public void accelerate() { speed = 100; } // Car inherits speed from Vehicle
}
Here, the Car class inherits the speed attribute and the start() method directly from the single
Vehicle class.
28. Define applicative order evaluation and normal order evaluation.
Applicative order evaluation (Strict Evaluation) is an evaluation strategy where all
arguments of a function are completely evaluated before the function itself is applied. This is
the standard behavior in most mainstream imperative and object-oriented languages (C,
C++, Java) because it is simple to implement and efficient when arguments are always
needed. The function only receives the calculated values of the arguments.
Normal order evaluation (Lazy Evaluation) is an evaluation strategy where the function is
applied first, and the arguments are evaluated only when their values are actually needed
within the function body. This approach can avoid unnecessary or redundant computations if
a function is called but does not use all of its arguments. Normal order evaluation is
characteristic of purely functional languages like Haskell.
29. What is multiple inheritance? Explain in detail the concept and
implementation of multiple inheritance.
Multiple inheritance is a type of inheritance in object-oriented programming where a single
derived class inherits properties and methods from more than one distinct base class. This
allows the derived class to combine and reuse the functionalities of several parent classes
simultaneously.
Implementation and the Diamond Problem: While powerful for code reuse, multiple
inheritance introduces the Diamond Problem (or ambiguity). This occurs if two parent
classes inherit from a common grandparent and both parents have a method or member
with the exact same name. When the final derived class attempts to use that member, the
compiler cannot determine which path (which parent's version) to follow. Languages handle
this: C++ supports multiple inheritance directly but requires scope resolution or virtual
inheritance to resolve the ambiguity, while Java avoids this problem by disallowing multiple
inheritance of classes, allowing it only through interfaces.
30. What is multilevel inheritance? Explain in detail the concept and
implementation of multilevel inheritance.
Multilevel inheritance is a form of inheritance that creates a chain or hierarchy of derived
classes, where one class inherits from a second class, which in turn inherits from a third
class (A -> B -> C). It establishes a grand-parent/parent/child relationship.
Concept and Implementation:
● The structure is linear: A is the base class, B is the intermediate class (inheriting from
A), and C is the derived class (inheriting from B).
● Class C gains access to the features of B and, indirectly, the features of A, promoting
code reuse across multiple levels. This form of inheritance is well-structured and
does not introduce the ambiguity issues associated with multiple inheritance.
Example:
class A { void showA() { } } // Grandparent
class B extends A { void showB() { } } // Parent, inherits A
class C extends B { void showC() { } } // Child, inherits B and A
Here, class C contains all members defined in A, B, and C itself.
31. What is a dangling pointer? Explain solutions to the dangling pointer
problem.
A dangling pointer is a pointer that still holds the memory address of a dynamically
allocated object that has already been deallocated (freed) back to the heap. If the program
attempts to access or use the memory location through this pointer, it leads to undefined
behavior, potentially causing data corruption, runtime errors, or program crashes.
Solutions to the Dangling Pointer Problem:
1. Set to NULL: The most basic solution is to immediately assign NULL (or an
equivalent null reference) to the pointer after the memory it pointed to has been
freed. Any subsequent access can then be safely caught as a null pointer
dereference.
2. Smart Pointers/Garbage Collection (GC): Using modern features like smart
pointers (C++) or relying on GC (Java, Python) automates memory management and
lifetime tracking, eliminating the manual risk of creating dangling pointers.
3. Tombstone Mechanism: In some systems, an intermediate memory cell
(tombstone) holds the real address. When memory is freed, the tombstone is marked
invalid, so any pointer attempting access through it is flagged as an error.
32. What is an enumeration type? Explain the design issues for
enumeration types.
An enumeration type (enum) is a user-defined ordinal data type that consists of a set of
named integer constant values (enumeration constants). It is primarily used to enhance code
readability and type safety by replacing "magic numbers" with meaningful names for a fixed
set of related choices (e.g., days of the week, error codes).
Design Issues for Enumeration Types:
1. Integer Equivalence: Should enumeration values be implicitly convertible to
integers, allowing arithmetic operations, or should they remain strictly distinct types
for stronger type safety?
2. Scope Control: Should the enumeration constants be scoped only within the
enumeration itself (like in C++) or should they leak into the surrounding scope (like in
C)?
3. Operations Allowed: Are operations like addition, subtraction, or comparisons other
than simple equality allowed on enumeration values? Restricting operations improves
safety but reduces flexibility.
4. Implicit Conversion: Should enumeration values be implicitly convertible to other
types (e.g., int), which is convenient but weakens type checking?
33. What is a union? Explain discriminated union and free union in
detail.
A union is a user-defined data type where all its members share the same memory
location. At any given time, only one member of the union can hold a valid value, and the
union's size is determined by its largest member. Unions are used to conserve memory
when it is known that only one type of data will be relevant at any point in time.
1. Discriminated Union (Tagged Union): This type of union includes an extra field,
called a discriminator or tag, which explicitly stores information about which
member of the union is currently active and valid. The tag ensures safe access by
allowing the program to check the active type before reading the data. Discriminated
unions (supported in Pascal, Ada) reduce runtime errors and are type-safe.
2. Free Union (Unsafe Union): This type of union does not include a discriminator
field. The programmer is solely responsible for knowing which member of the union
currently holds the valid data. While providing maximum memory efficiency, free
unions (supported in C) are inherently unsafe and error-prone, as accessing the
wrong member can lead to memory corruption or undefined behavior.
34. What is polymorphism? Explain object closure in detail.
Polymorphism ("many forms") is a cornerstone of object-oriented programming that allows
a single interface (such as a method name) to represent multiple different behaviors
depending on the object type on which it is invoked. This is primarily achieved through
method overriding in inheritance hierarchies, where the specific method execution is
resolved at runtime (dynamic binding), promoting flexibility and code reuse.
Object Closure: Object closure refers to the inherent binding of a method (function) to the
specific data (attributes) of the object instance upon which it is called. When you invoke
[Link](), the method is closed over the state of the myCar object (its current
speed, fuel level, etc.). This ensures that the method operates on the correct and current
context of that particular object instance. Object closure is essential for polymorphism to
work correctly, as it guarantees that even though the method name is the same across
multiple classes, the execution correctly manipulates the data of the specific runtime object.
35. What are the concepts of “tombstone” and “lock and key” in memory
management, and how do they help prevent issues like dangling
pointers and memory leaks?
Tombstone and Lock-and-Key are safety mechanisms used in memory management to
control access to dynamically allocated memory, primarily mitigating the risks of dangling
pointers (pointers referencing freed memory) and ensuring valid access.
1. Tombstone: This mechanism uses an intermediate cell in memory, the tombstone,
which holds the address of the dynamically allocated memory block. Pointers do not
reference the memory directly; they point only to the tombstone. When memory is
deallocated, the tombstone is marked as invalid. Any pointer attempting to access
the memory must first check the tombstone, which prevents the use of a dangling
pointer. However, this introduces extra memory overhead and an additional level of
indirection.
2. Lock-and-Key: This mechanism involves associating a unique key value with the
pointer itself and storing a corresponding lock value within the header of the
allocated memory block. Before a pointer is allowed to access the memory:
○ The system compares the pointer's key with the memory block's lock.
○ If the key and lock match, access is permitted.
○ If they do not match, the access is denied, preventing the pointer from
accessing memory that was freed or reassigned to another object. Both
mechanisms improve safety but incur runtime and memory overhead.
36. What do you understand by the terms “semantics of a call” and
“semantics of a return” in case of a simple subprogram? What do you
mean by the activation record and activation record instance?
The semantics of a call describes the detailed sequence of operations executed when a
subprogram (function/procedure) is invoked. These actions ensure proper control and data
transfer:
● Evaluation and passing of actual parameters to formal parameters.
● Allocation of memory space for the subprogram’s local variables.
● Saving the return address (where execution should resume) and the execution state
of the calling program.
● Transferring control to the entry point of the subprogram.
The semantics of a return describes the inverse sequence of operations executed when
the subprogram finishes:
● Returning result values (if any).
● Deallocating memory space used for local variables.
● Restoring the execution state of the calling program.
● Transferring control back to the saved return address.
An activation record is the generic data structure template used to manage all necessary
information for a single execution of a subprogram. It typically holds the return address, local
variables, parameters, and control links. An activation record instance is the actual copy of
the activation record created and pushed onto the runtime stack each time the subprogram
is called. In recursive calls, multiple instances of the same activation record exist
simultaneously.
37. What are the characteristics of subprograms? Explain in detail the
various types of parameters and their uses in different programming
languages.
A subprogram (function or procedure) is an essential program unit that performs a specific,
well-defined task.
Characteristics of Subprograms:
1. Single Entry Point: Execution always begins at the start of the subprogram body.
2. Parameterization: They can accept input data through parameters.
3. Result: They may return a value or result to the caller.
4. Local Environment: They possess their own set of local variables and an execution
environment distinct from the calling program.
5. Return of Control: Control is automatically transferred back to the calling program
upon completion.
Various Types of Parameters:
1. Call by Value: The subprogram receives a copy of the actual parameter's value.
Changes made to the formal parameter inside the subprogram do not affect the
original variable. This method is safe and commonly used for primitive types (e.g., C,
Java).
2. Call by Reference (Call by Sharing): The subprogram receives the address or
reference to the actual parameter. Changes made inside the subprogram directly
affect the original variable. This method is efficient for passing large data structures
(e.g., C++ references, Java for objects).
3. Call by Result: The formal parameter is uninitialized upon call. The actual parameter
receives the final value of the formal parameter only when the subprogram completes
execution.
4. Call by Value-Result: This combines the features of Call by Value and Call by
Result; the formal parameter is initialized with the actual parameter's value upon call,
and the final value of the formal parameter is copied back to the actual parameter
upon return (supported in Ada).
38. Difference between structure, union and enum
Feature Structure (struct) Union (union) Enumeration (enum)
Purpose To group related data To hold different To define a set of
elements of different types of data named, integer
types into a single elements in the constant values
named unit. same memory (ordinal type).
location to save
space.
Memory Separate Memory: Shared Memory: No direct allocation:
Allocation Each member is All members share Variables of this type
allocated its own distinct the same starting store a single integer
memory space. memory location. constant value.
Size The size is the sum of The size is equal to The size is typically the
the sizes of all individual the size of the size of an int.
members, often including largest single
padding. member.
Value All members can store Only one member Defines the constants;
Access and retain valid values can hold a valid used for assignment
simultaneously. value at any given and comparison.
time.
Data Types A collection of variables A collection of A set of integral
of possibly different variables of possibly constants (integers).
types. different types.
Runtime High, as members are Low (in free unions), High, as values are
Safety independent. as accidental restricted to predefined
access to the wrong constants.
member is possible.
Typical Use Representing complex Memory Improving readability
Case records (e.g., student optimization when by providing named
record, book inventory). data is mutually options (e.g., days of
exclusive (e.g., the week, state
variant records). machine modes).
Declaration struct union enum
Keyword