0% found this document useful (0 votes)
5 views

PPL QB Answers

The document discusses various programming concepts, including binding times, programming paradigms, attributes of good programming languages, computer construction methods, parameter passing methods, primitive data types, operator overloading, short circuit evaluation, and subprogram design issues. It provides definitions, examples, and explanations for each concept, highlighting their significance in programming. The content serves as a comprehensive overview of foundational programming principles and practices.

Uploaded by

sp5290657
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)
5 views

PPL QB Answers

The document discusses various programming concepts, including binding times, programming paradigms, attributes of good programming languages, computer construction methods, parameter passing methods, primitive data types, operator overloading, short circuit evaluation, and subprogram design issues. It provides definitions, examples, and explanations for each concept, highlighting their significance in programming. The content serves as a comprehensive overview of foundational programming principles and practices.

Uploaded by

sp5290657
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
You are on page 1/ 24

PPL QB ANSWERS

1. List the different classes of binding times. Explain with suitable example.

Answer:

Binding time refers to the point in the development or execution process when attributes of
program entities—such as variables, functions, or objects—are fixed or “bound” to their
corresponding values, types, or memory locations. The main classes of binding times are:

1. Language Design Time:

- Definition: This is when properties of language constructs are decided by the language
designer.

- Example: Deciding that in a language, an integer variable is fixed to a specific size (e.g.,
32-bit) is a design-time decision.

2. Compile Time:

- Definition: At compile time, many bindings, such as type-checking and constant values,
are determined. The compiler resolves references, checks types, and may even perform
optimizations based on constant expressions.

- Example: In C, if you write `const int x = 5;`, the value `5` is bound to `x` at compile
time. The compiler uses this information to check the rest of the code for correctness.

3. Link Time:

- Definition: Link time binding occurs when multiple compiled modules or object files are
combined to form an executable. At this stage, unresolved symbols or references between
modules are resolved.

- Example: In a multi-file C program, functions declared in one module but defined in


another are linked together at link time, binding the function calls to their definitions.

4. Load Time:

- Definition: Load time binding happens when the program is loaded into memory for
execution. The system loader assigns final memory addresses for the program’s code and
data.
- Example: A dynamically linked library (DLL) or shared library’s memory addresses are
resolved when the executable is loaded into memory. This allows the same library to be
used by different programs while using different memory addresses.

5. Run Time:

- Definition: Run time binding is the process when decisions are made during the actual
execution of the program. This includes actions like dynamic dispatch, memory allocation,
and binding variables to values resulting from user inputs or calculations.

- Example: In many object-oriented languages, method calls on polymorphic objects are


decided at run time. For instance, calling a method on an object of a subclass through a
base class pointer typically uses run time binding to determine the correct method to
execute (dynamic method dispatch).
2. Explain any two language paradigms with example.

Answer:

List of Programming Paradigms:

• Imperative Programming

• Declarative Programming

• Functional Programming

• Object-Oriented Programming

• Logic Programming

• Aspect-Oriented Programming

• Concurrent/Parallel Programming

1. Imperative Programming:

Description:
Imperative programming centers around describing how a program should achieve its
outcome through a sequence of statements that change program state. This paradigm uses
commands like loops, conditional statements, and variable assignments to produce a
result. The programmer lays out exact steps for the computer to follow.

Example in C that calculates the sum of numbers from 1 to 5:

#include <stdio.h>

int main() {

int sum = 0;

for (int i = 1; i <= 5; i++) {

sum += i;

printf("Sum is: %d\n", sum);

return 0;

}
• In this code, the loop iterates over the numbers, and the variable sum accumulates
the total. Each step is explicitly defined, which is characteristic of the imperative
approach.

2. Functional Programming:

• Description:
Functional programming is based on the concept of pure functions and avoids side
effects and mutable state. In this paradigm, computation is performed by applying and
composing functions, and results depend solely on the input parameters. This leads to
clearer, more predictable code as each function is like a mathematical function.

• Example:
Below is a simple example in Script that uses a functional programming approach to
calculate the sum of an array of numbers:

const numbers = [1, 2, 3, 4, 5];

const sum = numbers.reduce((accumulator, currentValue) =>


accumulator + currentValue, 0);

console.log("Sum is:", sum);

• In this example, the reduce function is used to combine the list of numbers into a
single sum, without any explicit state changes or iterative loops. The code
emphasizes the use of pure functions and immutability, key characteristics of
functional programming.
3. List attributes of a good programming language and explain any two in detail.
Answer:

A good programming language typically has the following attributes:

1. Simplicity and Readability


2. Expressiveness
3. Efficiency
4. Portability
5. Robustness and Reliability
6. Scalability and Maintainability
7. Support for Abstraction
8. Community and Library Support

• Simplicity and Readability:

A good programming language should have a simple syntax that is easy to learn and
understand. This reduces the effort needed to write, read, and maintain code. Readability
helps programmers quickly understand the codebase, which is especially important in
collaborative environments. For instance, languages like Python emphasize clean
indentation and straightforward syntax, making it easier to catch mistakes and debug the
program. Simple language design also minimizes the likelihood of errors, thereby
increasing the overall reliability of the software.

• Portability:

Portability refers to the ability of code written in a programming language to run on different
platforms and operating systems with little or no modification. A portable language
abstracts away underlying hardware or OS-specific details, enabling developers to write
code that is reusable in various environments. For example, languages that compile to
intermediate bytecode (like ) or that are interpreted (like Python) can run on multiple
operating systems without changes to the source code. This attribute is crucial for
developing cross-platform applications, reducing development and maintenance costs,
and ensuring broader usability of the software.
3. What are the different ways by which computer might be constructed? Explain
with example of web application.

Answer:

One way to interpret the question is by considering the various construction paradigms for
computers or computing systems. In general, computers can be constructed in the
following ways:

Hardware Construction

Traditional computers are built from physical components (CPUs, memory, input/output
devices) assembled on a circuit board. The design can follow various architectures such
as:

Von Neumann Architecture: Uses a single memory space for both instructions and data.

Harvard Architecture: Separates memory for instructions and data, allowing simultaneous
access.

Example in a Web Application:

A web application running on a physical server uses processors, RAM, and storage built
with these hardware principles. For instance, a server hosting a website might use a multi-
core CPU and large RAM to handle many simultaneous users.

Distributed and Networked Systems

Instead of a single physical machine, modern computing often involves a distributed


system where several computers (or nodes) work together to provide the overall
functionality.

Distributed Architecture: Splits tasks among multiple computers to improve scalability and
reliability.

Cloud Computing: Utilizes virtualized resources spread over many physical machines in
data centers.

Example in a Web Application:

A web application like an e-commerce platform might be architected using a distributed


system. One set of servers handles the user interface (the front end), another group runs
the business logic (application servers), and yet another manages data storage (database
systems). This separation improves performance and fault tolerance because if one node
fails, others can compensate.
Virtualization and Software Abstraction

Instead of direct hardware interaction, many modern systems use virtual machines or
containers where software creates an "artificial" computer environment on top of physical
hardware.

Virtual Machines (VMs): Emulate a complete computer system, including hardware.

Containers: Package code and dependencies together, running isolated from other
processes.

Example in a Web Application:

Many web applications are deployed using containers (like Docker) managed in an
orchestration system (like Kubernetes). This approach allows developers to build, test, and
deploy applications in environments that mimic real hardware but are abstracted,
scalable, and consistent across different platforms.
4. What are different parameters passing methods in programming languages with
example.

Answer: In programming languages, parameter passing methods refer to the ways in which
arguments are passed from a calling function to a called function. There are several
parameter passing methods, including:

• Pass by Value: In this method, a copy of the original value is passed to the called
function. Any changes made to the parameter within the called function do not affect
the original value in the calling function.
Example: In C, when we pass an integer variable to a function, its value is copied and
passed to the function. If the function modifies the value, it does not affect the original
variable.
• Pass by Reference: In this method, a reference to the original value is passed to the
called function. Any changes made to the parameter within the called function affect
the original value in the calling function.
Example: In C++, when we pass an integer variable to a function using a pointer or a
reference, any changes made to the parameter within the function affect the original
variable.
• Pass by Name: In this method, the actual parameter is not evaluated until it is used
within the called function. This method is not commonly used in modern programming
languages.
Example: In Algol, a programming language developed in the 1950s, pass by name was
used. When a parameter was passed to a function, its value was not evaluated until it
was used within the function.
• Pass by Constant: In this method, a copy of the original value is passed to the called
function, but the called function is not allowed to modify the value.
Example: In C++, when we pass a variable to a function using the const keyword, the
function is not allowed to modify the value.
• Pass by Result: In this method, the called function returns a value to the calling
function, which is then assigned to the original variable.
Example: In functional programming languages, such as Haskell, pass by result is used.
The called function returns a value, which is then assigned to the original variable.
• Pass by Value-Result: In this method, a copy of the original value is passed to the called
function, and the called function returns a value to the calling function, which is then
assigned to the original variable.
Example: In Ada, a programming language developed in the 1980s, pass by value-result
is used. The called function receives a copy of the original value and returns a value,
which is then assigned to the original variable.
5. What are the different primitive data types? Explain with the examples of
syntax, size and ranges.

Answer:

Primitive data types are the basic building blocks for data manipulation in many
programming languages. They are not objects, and they store simple values. The following
are common primitive data types:

1. Integer Types (int, short, long, byte):

- int:

- Syntax (/C/C++):

int number = 100;

- Size: Typically 4 bytes (32 bits).

- Range: Usually from –2,147,483,648 to 2,147,483,647.

- short:

- Syntax:

short s = 30000;

- Size: Typically 2 bytes (16 bits).

- Range: Usually from –32,768 to 32,767.

- long:

- Syntax:

long bigNumber = 100000L;

- Size: Typically 8 bytes (64 bits).

- Range: Approximately –9,223,372,036,854,775,808 to 9,223,372,036,854,775,807.

- byte:

- Syntax:

byte smallNumber = 100;

- Size: 1 byte (8 bits).

- Range: Pronounced range from –128 to 127.


2. Floating-Point Types (float and double):

- float:

- Syntax:

float pi = 3.14f;

- Size: Typically 4 bytes (32 bits).

- Range: Provides approximately 6-7 decimal digits of precision; accepted range is large,
but precision is limited.

- double:

- Syntax:

double piPrecise = 3.141592653589793;

- Size: Typically 8 bytes (64 bits).

- Range: Provides approximately 15-16 decimal digits of precision. It allows for a much
smaller error in calculations than float.

3. Character Type (char):

- Syntax:

char letter = 'A';

- Size: Typically 2 bytes (16 bits) in (to support Unicode); in C/C++ it is typically 1 byte.

- Range: In , it can represent characters with Unicode values from `'\u0000'` (0) to
`'\uffff'` (65,535). In the C/C++ context, the range depends on the encoding used.

4. Boolean Type (boolean):

- Syntax:

boolean flag = true;

- Size: Not defined precisely in languages like ; it simply holds true or false values.

- Range: Only two values: `true` and `false`.


7. Explain following concepts with example:

i) Overloaded unary operator

ii) Short circuit evaluation

Answer:

i) Overloaded Unary Operator

Operator overloading is a feature in some programming languages (such as C++) that


allows operators to be redefined and used with user-defined data types (classes). The
unary operator is an operator that takes only one operand. Overloading a unary operator
means giving a new behavior to an operator when it is applied to objects of a user-defined
class.

Consider a class representing a number. We might want to overload the unary minus (-)
operator so that it negates the value stored in an object of that class.

#include <iostream>

using namespace std;

class Number {

private:

int value;

public:

Number(int val) : value(val) {}

// Overloading the unary minus operator

Number operator-() const {

return Number(-value);

void display() const {

cout << "Value: " << value << endl;

};

int main() {
Number n(10);

Number neg = -n; // Calls the overloaded unary minus operator

n.display(); // Output: Value: 10

neg.display(); // Output: Value: -10

return 0;

In the above example:

- The `operator-()` function is defined in the `Number` class.

- When we write `-n`, the overloaded unary operator is called, and it returns a new
`Number` object with the value negated.

ii) Short Circuit Evaluation

Short circuit evaluation is a programming language feature where the evaluation of a logical
expression stops as soon as the outcome is determined. This is typically used with the
logical operators AND (`&&`) and OR (`||`). When using these operators, if the result can
be determined from the first operand, the second operand is not evaluated.

Consider the logical AND (`&&`) operator where the first operand is false. In such a case,
even if the second operand involves a function call or computation, it won’t be executed
because the entire expression will definitely be false.

#include <iostream>

using namespace std;

bool checkSecond() {

cout << "checkSecond() was called." << endl;

return true;

int main() {

bool condition = false; // First operand is false

if (condition && checkSecond()) { // Due to short circuit


evaluation, checkSecond() won't be called.
cout << "Both conditions are true." << endl;

} else {

cout << "At least one condition is false." << endl;

return 0;

In the above example:

- The expression `condition && checkSecond()` is evaluated.

- Since `condition` is false, the program does not call `checkSecond()`, because
regardless of its return value, the whole expression is false. This is short circuit evaluation
in action.
8. What are subprograms? List and explain the design issues for subprograms.

Answer:

Subprograms Overview

Subprograms (also known as procedures, functions, or methods) are self-contained blocks


of code designed to perform a specific task. They are an essential feature of structured and
modular programming because they allow developers to organize code into reusable,
manageable, and logically separate units. Subprograms improve readability,
maintainability, and can facilitate testing and debugging.

Design Issues for Subprograms

When designing subprograms, the following issues should be considered:

1. Interface Design (Parameters and Return Values):

- Parameter Types and Number: Decide what inputs are necessary for the subprogram.
This includes the data types and the number of parameters needed.

- Return Type: Determine if the subprogram should return a value and what type it should
be.

- Readability and Intuitiveness: The names and order of parameters should be clear and
reflect their roles, making the subprogram easy for others to use.

2. Parameter Passing Mechanism:

- Pass-by-Value vs. Pass-by-Reference: Decide whether arguments are to be passed by


value (where a copy is made) or by reference (where the subprogram accesses the original
data). Pass-by-value protects the original data, while pass-by-reference allows the
subprogram to modify the caller’s variables.

- Side Effects: Consider how changes within the subprogram affect external variables.
Minimizing side effects can lead to more predictable and maintainable code.

3. Scope and Lifetime of Variables:

- Local vs. Global Variables: Determine which variables should be local (visible only
within the subprogram) to prevent unintended interference from other parts of the program.

- Lifetime Management: Ensure that the variables declared within a subprogram are valid
only during its execution unless explicitly required otherwise (as with static variables).

4. Modularity and Reusability:


- Purpose and Cohesion: The subprogram should perform a single, well-defined task. This
improves modularity and encourages code reuse.

- Encapsulation: Hide the internal implementation details so that the subprogram’s user
interacts only with its interface. This abstraction simplifies changes in the implementation
later.

5. Error Handling and Robustness:

- Input Validation: The subprogram should validate its parameters to handle unexpected
or erroneous inputs gracefully.

- Return Mechanisms for Errors: Design a strategy for error reporting, either through
special return values, exceptions, or error codes. This ensures that errors are detected and
handled appropriately by the caller.

6. Documentation and Naming Conventions:

- Clear Documentation: Provide comments or documentation that explain the


subprogram’s purpose, parameters, return value, and any exceptions or side effects.

- Naming Consistency: Use consistent, descriptive naming for subprograms and


parameters to facilitate readability and maintenance.

7. Recursion and Termination:

- Proper Base Case: When using recursion, ensure that there is a clearly defined base
case to prevent infinite recursion.

- Efficiency Considerations: Consider the performance implications of recursive versus


iterative solutions and choose accordingly.
9. Illustrate the Impact of machine architecture on programming languages.

i) Hardware

ii) Firmware

iii) Software

Answer:

Impact of Machine Architecture on Programming Languages

Machine architecture directly influences the design, functionality, and performance of


programming languages. The architecture is comprised of three fundamental layers:
hardware, firmware, and software. Each layer interacts with programming languages in
different ways:

1. Hardware

- Definition and Role:

Hardware refers to the physical components of a computer system such as the CPU,
memory, input/output devices, and storage. The hardware's capabilities set the limits and
opportunities for language design.

- Impact on Programming Languages:

- Instruction Set Architecture (ISA): Programming languages, especially low-level


languages like assembly, are closely tied to the processor's ISA. High-level languages,
however, rely on compilers to translate code into machine instructions that comply with
the ISA.

- Performance Considerations: The speed and efficiency of hardware components


influence how languages and their runtimes manage tasks like memory allocation, parallel
processing, and input/output operations.

- Data Representation: Hardware dictates how data types (e.g., integers, floating-point
numbers) are represented in memory. This affects language design decisions regarding
precision, memory management, and performance tuning.

- Example:

In C/C++, the size of data types such as int or long may vary across different hardware
architectures (32-bit vs. 64-bit systems), impacting portability and efficiency. Compiler
optimizations are often hardware-specific to leverage the processor's capabilities.
2. Firmware

- Definition and Role:

Firmware is specialized software programmed into the hardware (often stored in non-
volatile memory) that provides low-level control for the device's specific hardware. It acts
as a bridge between the physical hardware and higher-level software.

- Impact on Programming Languages:

- Bootstrapping and Initialization: Firmware (e.g., BIOS or UEFI) initializes hardware


components and loads the operating system. Programming languages used for system-
level development must be designed to work within the constraints and capabilities
provided by the firmware.

- Hardware Abstraction: Firmware dictates standardized interfaces (APIs) by which


higher-level software accesses hardware resources. This influences the design of system
libraries and runtime environments in programming languages.

- Embedded Systems: In environments where firmware controls the entire system (such
as embedded devices), programming languages are often tailored for low-level hardware
control, minimal resource consumption, and real-time responsiveness. Languages like C,
or specialized versions of C++, are common.

- Example:

In embedded programming, a developer might write code in C that directly manipulates


hardware registers. The firmware provides predefined APIs or memory-mapped I/O
addresses to interact with sensors or actuators, and the programming language must
accommodate these low-level operations effectively.

3. Software

- Definition and Role:

Software encompasses the operating systems, libraries, runtime environments, and


applications that run atop the underlying hardware and firmware. It provides higher-level
abstraction and functionality.

- Impact on Programming Languages:

- Operating System Services: Programming languages must operate with the services
provided by the operating system, such as process management, file systems, networking,
and security. The design of these service interfaces influences how languages structure
their standard libraries and runtime systems.
- Programming Models: The architecture of software (e.g., multi-threading, distributed
systems) influences language features like concurrency primitives, exception handling, and
memory management. Language runtime systems are designed to interface efficiently with
OS services.

- Virtual Machines and Interpreters: Some high-level languages run on virtual machines
(such as the JVM for or CLR for C#) to provide portability across different hardware
architectures. This abstraction layer allows the language to overcome differences in
hardware capabilities.

- Performance Optimization: The efficiency of the software stack—including compilers,


interpreters, and runtime libraries—depends on how well they are optimized for a given
hardware and firmware combination, influencing language performance and
responsiveness.

- Example:

Modern languages like and Python depend on high-level operating system features and
virtual machine optimizations in order to provide cross-platform compatibility. Their design
abstracts away the underlying hardware details, while still requiring awareness of OS-level
characteristics (like memory management and process scheduling).
10. Describe ordinal types: enumeration with 'C++' example.

Answer:

Ordinal types are data types whose values have a defined order. In other words, they allow
us to compare values using relational operators like <, >, or ==. Common examples of
ordinal types include integral types (like int or char) as well as enumerated types (enums).

Enumeration in C++

In C++, we can define an enumeration type using the keyword `enum`. An enum allows us
to define a set of named integer constants. Each constant in an enum is automatically
assigned a corresponding integer value starting from 0 (unless specified otherwise).
Because these values are integer-based and ordered, they qualify as ordinal types.

Example:

#include <iostream>

using namespace std;

enum Color {

RED, // Automatically assigned 0

GREEN, // Automatically assigned 1

BLUE // Automatically assigned 2

};

int main() {

Color myColor = GREEN;

// Comparing ordinal values

if (myColor < BLUE) {

cout << "The color comes before BLUE in the enumeration."


<< endl;

}
// Printing the integer value of myColor

cout << "The integer value of myColor is: " << myColor <<
endl;

return 0;

Explanation:

1. Definition:

The enum `Color` defines three possible values—`RED`, `GREEN`, and `BLUE`—
which are automatically assigned the values 0, 1, and 2 respectively.

2. Usage:

In the `main` function, we declare a variable `myColor` of type `Color` and assign it the
value `GREEN`.

3. Ordinal Nature:

Since each enumerated value corresponds to an integer, you can perform comparisons
(e.g., `myColor < BLUE`). This comparison is valid because the underlying integer values
provide a natural ordering (from 0 upward).

4. Output:

Running this program will print that `myColor` comes before `BLUE` and display its
underlying integer value.
11. Consider the following program code and identify the semantic elements of the
programming language along with type of binding. Describe the same

#include <stdio.h>

int main()

int x, y;

scanf("%d%d", &x, &y);

int temp;

temp = x;

x = y;

y = temp;

printf("%d %d\n", x, y);

return 0;

}
Answer:
1. Semantic Elements:

• Preprocessor Directive:

- The line #include <stdio.h> tells the compiler to include the Standard Input/Output
library, enabling use of scanf and printf.

• Function Declaration:

- The main() function is declared as int main() and serves as the starting point of the
program.

• Variable Declarations and Scope:

- Two integer variables (x and y) are declared in the main block and are available
throughout the entire main function.

- A temporary variable (temp) is declared inside an inner block. Its scope is limited to
that block, meaning it is only accessible and valid within the braces where it is declared.
• Input/Output Statements:

- scanf("%d%d", &x, &y) reads two integers from the user and stores them in x and y.

- printf("%d %d\n", x, y) prints the swapped values of the variables later in the code.

• Block Structure:

- The inner block defined with curly braces { … } provides a local scope for temp,
ensuring that its binding does not interfere with any variables declared outside the block.

2. Binding Types:

• Static (Lexical) Binding:

- The identifiers x, y, and temp are bound to their types during compile time. The
compiler knows the type and scope of these variables when processing the code.

- x and y, declared in main, are accessible throughout main, while temp is only
accessible inside its inner block.

- Function calls to scanf and printf are also resolved at compile/link time with bindings
to the standard library.

• Run-Time Operations:

- Even though the binding of the variables is static, the actual evaluation of
expressions (e.g., swapping values using temp) happens at runtime.
12. Write short note on:

i) Mixed mode Assignment

ii) Unconditional branching

Answer:

1. Mixed Mode Assignment:

• Definition:

- Mixed mode assignment occurs when an assignment statement involves different


data types on the two sides. Typically, it happens when a value of one data type is assigned
to a variable of another data type (e.g., assigning a float to an int).

• How It Works:

- The compiler performs implicit type conversion (also known as coercion) so that
the value on the right-hand side fits into the type of the left-hand side variable.

- This conversion might involve truncation (e.g., converting float 3.9 into int 3),
possible loss of precision, or other adjustments depending on the data types involved.

• Importance:

- Mixed mode assignments are common in programming but require careful


attention to avoid unintended loss of data or precision.

- They illustrate the language’s ability to handle operations with operands of


different types by automatically converting one operand to match the other.

2. Unconditional Branching:

• Definition:

- Unconditional branching is a control-flow mechanism that causes the program to


jump to another part of the code without evaluating any condition.

- It is implemented using statements such as the goto statement in C.

• How It Works:

- When the flow of execution reaches an unconditional branch statement like goto,
the program immediately transfers control to the label specified in the statement.

- There is no decision-making process; the jump occurs every time the statement is
executed.
• Importance and Caution:

- Unconditional branching provides a powerful but potentially dangerous


mechanism because it can lead to “spaghetti code” if overused or used without clear
structure.

- While useful in certain low-level programming scenarios (such as error handling or


escaping deeply nested loops), its use is generally discouraged in favor of structured
programming constructs to ensure code clarity and maintainability.

Summary:

Mixed mode assignment allows conversion between different data types during
assignment, relying on implicit type coercion, while unconditional branching provides a
direct jump to another part of the code without conditions. Both concepts are fundamental
in understanding how programming languages manage data types and control flow.

You might also like