Module 06
Intructors:
Abir Das and
Sourangshu Module 06: Programming in C++
Bhattacharya
Constants and Inline Functions
Objectives &
Outline
const-ness &
cv-qualifier
const-ness
Intructors: Abir Das and Sourangshu Bhattacharya
Advantages
Pointers
volatile Department of Computer Science and Engineering
Indian Institute of Technology, Kharagpur
inline
functions
{abir, sourangshu}@cse.iitkgp.ac.in
Macros
inline
Summary
Slides taken from NPTEL course on Programming in C++
by Prof. Partha Pratim Das
CS20202: Software Engineering Intructors: Abir Das and Sourangshu Bhattacharya 1
Module Objectives
Module 06
Intructors:
Understand const in C++ and contrast with Manifest
Abir Das and
Sourangshu
Constants
Bhattacharya
Understand inline in C++ and contrast with Macros
Objectives &
Outline
const-ness &
cv-qualifier
const-ness
Advantages
Pointers
volatile
inline
functions
Macros
inline
Summary
CS20202: Software Engineering Intructors: Abir Das and Sourangshu Bhattacharya 2
Module Outline
Module 06
const-ness and cv-qualifier
Notion of const
Intructors:
Abir Das and Advantages of const
Sourangshu
Bhattacharya Natural Constants – π, e
Program Constants – array size
Objectives & Prefer const to #define
Outline
const and pointer
const-ness &
cv-qualifier const-ness of pointer / pointee. How to decide?
const-ness
Advantages Notion of volatile
Pointers
volatile inline functions
inline Macros with params
functions
Macros Advantages
inline Disadvantages
Summary Notion of inline functions
Advantages
CS20202: Software Engineering Intructors: Abir Das and Sourangshu Bhattacharya 3
Program 06.01: Manifest constants in C
Module 06 Manifest constants are defined by #define
Intructors: Manifest constants are replaced by CPP (C Pre-Processor)
Abir Das and
Source Program Program after CPP
Sourangshu
Bhattacharya #include <iostream> // Contents of <iostream> header replaced by CPP
#include <cmath> // Contents of <cmath> header replaced by CPP
Objectives & using namespace std; using namespace std;
Outline
#define TWO 2 // #define of TWO consumed by CPP
const-ness & #define PI 4.0*atan(1.0) // #define of PI consumed by CPP
cv-qualifier
const-ness int main() { int main() {
Advantages
int r = 10; int r = 10;
Pointers
double peri = double peri =
volatile
TWO * PI * r; 2 * 4.0*atan(1.0) * r; // Replaced by CPP
cout << "Perimeter = " cout << "Perimeter = "
inline << peri << endl; << peri << endl;
functions return 0; return 0;
Macros } }
inline
Summary Perimeter = 314.159 Perimeter = 314.159
• TWO is a manifest constant • CPP replaces the token TWO by 2
• PI is a manifest constant • CPP replaces the token PI by 4.0*atan(1.0)
• TWO & PI look like variables • Compiler sees them as constants
CS20202: Software Engineering Intructors: Abir Das and Sourangshu Bhattacharya 4
Notion of const-ness
The value of a const variable cannot be changed after definition
Module 06
const int n = 10; // n is an int type variable with value 10
Intructors: // n is a constant
Abir Das and ...
Sourangshu n = 5; // Is a compilation error as n cannot be changed
Bhattacharya ...
int m;
int *p = 0;
Objectives & p = &m; // Hold m by pointer p
Outline *p = 7; // Change m by p; m is now 7
const-ness & ...
cv-qualifier p = &n; // Is a compilation error as n may be changed by *p = 5;
const-ness
Advantages Naturally, a const variable must be initialized when defined
Pointers
volatile const int n; // Is a compilation error as n must be initialized
inline
functions A variable of any data type can be declared as const
Macros
inline typedef struct _Complex {
double re;
Summary double im;
} Complex;
const Complex c = {2.3, 7.5}; // c is a Complex type variable
// It is initialized with c.re = 2.3 and c.im = 7.5
// c is a constant
...
c.re = 3.5; // Is a compilation error as no part of c can be changed
CS20202: Software Engineering Intructors: Abir Das and Sourangshu Bhattacharya 5
Program 06.02: Compare #define and const
Module 06 Using #define Using const
Intructors: #include <iostream> #include <iostream>
Abir Das and #include <cmath> #include <cmath>
Sourangshu using namespace std; using namespace std;
Bhattacharya
#define TWO 2 const int TWO = 2;
#define PI 4.0*atan(1.0) const double PI = 4.0*atan(1.0);
Objectives &
Outline int main() { int main() {
int r = 10; int r = 10;
const-ness & double peri = double peri =
cv-qualifier TWO * PI * r; TWO * PI * r; // No replacement by CPP
const-ness cout << "Perimeter = " cout << "Perimeter = "
Advantages << peri << endl; << peri << endl;
Pointers return 0; return 0;
volatile } }
inline
functions Perimeter = 314.159 Perimeter = 314.159
Macros
inline
• TWO is a manifest constant • TWO is a const variable initialized to 2
Summary • PI is a manifest constant • PI is a const variable initialized to 4.0*atan(1.0)
• TWO & PI look like variables • TWO & PI are variables
• Types of TWO & PI may be indeterminate • Type of TWO is const int
• Type of PI is const double
CS20202: Software Engineering Intructors: Abir Das and Sourangshu Bhattacharya 6
Advantages of const
Natural Constants like π, e, Φ (Golden Ratio) etc. can be
Module 06
compactly defined and used
Intructors:
Abir Das and const double pi = 4.0*atan(1.0); // pi = 3.14159
Sourangshu const double e = exp(1.0); // e = 2.71828
Bhattacharya const double phi = (sqrt(5.0) + 1) / 2.0; // phi = 1.61803
const int TRUE = 1; // Truth values
Objectives & const int FALSE = 0;
Outline
const int null = 0; // null value
const-ness &
cv-qualifier
const-ness Note: NULL is a manifest constant in C/C++ set to 0.
Advantages
Pointers Program Constants like number of elements, array size etc. can
volatile be defined at one place (at times in a header) and used all over
inline the program
functions
Macros const int nArraySize = 100;
inline const int nElements = 10;
Summary int main() {
int A[nArraySize]; // Array size
for (int i = 0; i < nElements; ++i) // Number of elements
A[i] = i * i;
return 0;
}
CS20202: Software Engineering Intructors: Abir Das and Sourangshu Bhattacharya 7
Advantages of const
Module 06 Prefer const over #define
Intructors: Using #define Using const
Abir Das and
Sourangshu Manifest Constant Constant Variable
Bhattacharya
• Is not type safe • Has its type
• Replaced textually by CPP • Visible to the compiler
Objectives & • Cannot be watched in debugger • Can be watched in debugger
Outline • Evaluated as many times as replaced • Evaluated only on initialization
const-ness &
cv-qualifier
const-ness
Advantages
Pointers
volatile
inline
functions
Macros
inline
Summary
CS20202: Software Engineering Intructors: Abir Das and Sourangshu Bhattacharya 8
const and Pointers
Module 06 const-ness can be used with Pointers in one of the two ways:
Intructors: Pointer to Constant data where the pointee (pointed
Abir Das and
Sourangshu data) cannot be changed
Bhattacharya
Constant Pointer where the pointer (address) cannot be
Objectives &
changed
Outline
Consider usual pointer-pointee computation (without const):
const-ness &
cv-qualifier int m = 4;
const-ness int n = 5;
Advantages int * p = &n; // p points to n. *p is 5
Pointers ...
volatile n = 6; // n and *p are 6 now
*p = 7; // n and *p are 7 now. POINTEE changes
inline ...
functions p = &m; // p points to m. *p is 4. POINTER changes
Macros *p = 8; // m and *p are 8 now. n is 7. POINTEE changes
inline
Summary
CS20202: Software Engineering Intructors: Abir Das and Sourangshu Bhattacharya 9
const and Pointers: Pointer to Constant data
Module 06
Consider pointed data
Intructors:
Abir Das and int m = 4;
Sourangshu const int n = 5;
Bhattacharya const int * p = &n;
...
n = 6; // Error: n is constant and cannot be changed
Objectives & *p = 7; // Error: p points to a constant data (n) that cannot be changed
Outline p = &m; // Okay
*p = 8; // Error: even though m is not constant, it cannot be changed through p
const-ness &
cv-qualifier
const-ness Interestingly,
Advantages
Pointers int n = 5;
volatile const int * p = &n;
...
inline n = 6; // Okay
functions *p = 6; // Error: p points to a ’constant’ data (n) that cannot be changed
Macros
inline
Finally,
Summary
const int n = 5;
int * p = &n; // Error: If this were allowed, we would be able to change constant n
...
n = 6; // Error: n is constant and cannot be changed
*p = 6; // Would have been okay, if declaration of p were valid
CS20202: Software Engineering Intructors: Abir Das and Sourangshu Bhattacharya 10
const and Pointers: Example
Module 06 What will be the output of the following program:
Intructors: #include <iostream>
Abir Das and
Sourangshu using namespace std;
Bhattacharya
int main() {
Objectives & const int a = 5;
Outline int *b;
const-ness & b = (int *) &a;
cv-qualifier *b = 10;
const-ness
Advantages
cout << a << " " <<b<<" "<< &a <<" "<< *b <<"\n";
Pointers }
volatile
inline
functions
Macros
inline
Summary
CS20202: Software Engineering Intructors: Abir Das and Sourangshu Bhattacharya 11
const and Pointers: Example
Module 06 What will be the output of the following program:
Intructors: #include <iostream>
Abir Das and
Sourangshu using namespace std;
Bhattacharya
int main() {
Objectives & const int a = 5;
Outline int *b;
const-ness & b = (int *) &a;
cv-qualifier *b = 10;
const-ness
Advantages
cout << a << " " <<b<<" "<< &a <<" "<< *b <<"\n";
Pointers }
volatile
inline
functions Standard g++ compiler prints: 5 0x16b58f4ec 0x16b58f4ec 10
Macros b actually points to a
inline
But when accessed through a the compiler substitutes the constant expression
Summary Technically the behavior is undefined
CS20202: Software Engineering Intructors: Abir Das and Sourangshu Bhattacharya 12
const and Pointers: Constant Pointer
Module 06
Consider pointer
Intructors: int m = 4, n = 5;
Abir Das and int * const p = &n;
Sourangshu ...
Bhattacharya n = 6; // Okay
*p = 7; // Okay. Both n and *p are 7 now
...
Objectives & p = &m; // Error: p is a constant pointer and cannot be changed
Outline
const-ness & By extension, both can be const
cv-qualifier
const-ness const int m = 4;
Advantages const int n = 5;
Pointers const int * const p = &n;
volatile ...
n = 6; // Error: n is constant and cannot be changed
inline *p = 7; // Error: p points to a ’constant’ data (n) that cannot be changed
functions ...
Macros p = &m; // Error: p is a constant pointer and cannot be changed
inline
Summary Finally, to decide on const-ness, draw a mental line through *
int n = 5;
int * p = &n; // non-const-Pointer to non-const-Pointee
const int * p = &n; // non-const-Pointer to const-Pointee
int * const p = &n; // const-Pointer to non-const-Pointee
const int * const p = &n; // const-Pointer to const-Pointee
CS20202: Software Engineering Intructors: Abir Das and Sourangshu Bhattacharya 13
const and Pointers: The case of C-string
Module 06
Consider the example:
char * str = strdup("IIT, Kharagpur");
Intructors: str[0] = ’N’; // Edit the name
Abir Das and cout << str << endl;
Sourangshu str = strdup("JIT, Kharagpur"); // Change the name
Bhattacharya cout << str << endl;
Objectives & Output is:
Outline
NIT, Kharagpur
const-ness & JIT, Kharagpur
cv-qualifier
const-ness To stop editing the name:
Advantages
Pointers const char * str = strdup("IIT, Kharagpur");
volatile str[0] = ’N’; // Error: Cannot Edit the name
str = strdup("JIT, Kharagpur"); // Change the name
inline
functions To stop changing the name:
Macros
inline char * const str = strdup("IIT, Kharagpur");
str[0] = ’N’; // Edit the name
Summary str = strdup("JIT, Kharagpur"); // Error: Cannot Change the name
To stop both:
const char * const str = strdup("IIT, Kharagpur");
str[0] = ’N’; // Error: Cannot Edit the name
str = strdup("JIT, Kharagpur"); // Error: Cannot Change the name
CS20202: Software Engineering Intructors: Abir Das and Sourangshu Bhattacharya 14
Notion of volatile
Module 06
Variable Read-Write
The value of a variable can be read and / or assigned at
Intructors:
Abir Das and any point of time
Sourangshu
Bhattacharya The value assigned to a variable does not change till a
next assignment is made (value is persistent)
Objectives &
Outline const
const-ness & The value of a const variable can be set only at
cv-qualifier
const-ness
initialization – cannot be changed afterwards
Advantages
Pointers
volatile
volatile
In contrast, the value of a volatile variable may be
inline
functions different every time it is read – even if no assignment has
Macros been made to it
inline
A variable is taken as volatile if it can be changed by
Summary
hardware, the kernel, another thread etc.
cv-qualifier: A declaration may be prefixed with a
qualifier – const or volatile
CS20202: Software Engineering Intructors: Abir Das and Sourangshu Bhattacharya 15
Using volatile
Module 06
Consider:
Intructors: static int i;
Abir Das and void fun(void) {
Sourangshu i = 0;
Bhattacharya while (i != 100);
}
Objectives &
Outline
This is an infinite loop! Hence the compiler should optimize as:
const-ness & static int i;
cv-qualifier void fun(void) {
const-ness i = 0;
Advantages
while (1); // Compiler optimizes
Pointers
}
volatile
inline
Now qualify i as volatile:
functions
static volatile int i;
Macros
void fun(void) {
inline
i = 0;
Summary while (i != 100); // Compiler does not optimize
}
Being volatile, i can be changed by hardware anytime. It waits till
the value becomes 100 (possibly some hardware writes to a port).
CS20202: Software Engineering Intructors: Abir Das and Sourangshu Bhattacharya 16
Program 06.03: Macros with Parameters
Module 06 Macros with Parameters are defined by #define
Intructors: Macros with Parameters are replaced by CPP
Abir Das and Source Program Program after CPP
Sourangshu
Bhattacharya #include <iostream> // Contents of <iostream> header replaced by CPP
using namespace std; using namespace std;
Objectives &
Outline #define SQUARE(x) x * x // #define of SQUARE(x) consumed by CPP
const-ness & int main() { int main() {
cv-qualifier int a = 3, b; int a = 3, b;
const-ness
Advantages
b = SQUARE(a); b = a * a; // Replaced by CPP
Pointers
cout << "Square = " cout << "Square = "
volatile
<< b << endl; << b << endl;
inline return 0; return 0;
functions } }
Macros
inline
Square = 9 Square = 9
Summary
• SQUARE(x) is a macro with one param • CPP replaces the SQUARE(x) substituting x with a
• SQUARE(x) looks like a function • Compiler does not see it as function
CS20202: Software Engineering Intructors: Abir Das and Sourangshu Bhattacharya 17
Pitfalls of macros
Module 06
Consider the example:
#include <iostream>
Intructors:
using namespace std;
Abir Das and
Sourangshu
#define SQUARE(x) x * x
Bhattacharya
int main() {
Objectives & int a = 3, b;
Outline
b = SQUARE(a + 1); // Wrong macro expansion
const-ness &
cv-qualifier cout << "Square = " << b << endl;
const-ness
Advantages return 0;
Pointers }
volatile
inline
Output is 7 in stead of 16 as expected. On the expansion line it gets:
functions
b = a + 1 * a + 1;
Macros
inline
To fix:
Summary
#define SQUARE(x) (x) * (x)
Now:
b = (a + 1) * (a + 1);
CS20202: Software Engineering Intructors: Abir Das and Sourangshu Bhattacharya 18
Pitfalls of macros
Module 06
Continuing ...
Intructors: #include <iostream>
Abir Das and using namespace std;
Sourangshu
Bhattacharya #define SQUARE(x) (x) * (x)
int main() {
Objectives & int a = 3, b;
Outline
b = SQUARE(++a);
const-ness &
cv-qualifier cout << "Square = " << b << endl;
const-ness
Advantages return 0;
Pointers }
volatile
inline Output is 25 in stead of 16 as expected. On the expansion line it gets:
functions
Macros b = (++a) * (++a);
inline
Summary and a is incremented twice before being used! There is no easy fix.
CS20202: Software Engineering Intructors: Abir Das and Sourangshu Bhattacharya 19
inline Function
Module 06
Intructors: An inline function is just another functions
Abir Das and
Sourangshu The function prototype is preceded by the keyword inline
Bhattacharya
An inline function is expanded (inlined) at the site of its call
Objectives &
Outline and the overhead of passing parameters between caller and
const-ness & callee (or called) functions is avoided
cv-qualifier
const-ness
Advantages
Pointers
volatile
inline
functions
Macros
inline
Summary
CS20202: Software Engineering Intructors: Abir Das and Sourangshu Bhattacharya 20
Program 06.04: Macros as inline Functions
Module 06 Define the function
Intructors: Prefix function header with inline
Abir Das and
Sourangshu Compile function body and function call together
Bhattacharya
Using macro Using inline
Objectives & #include <iostream> #include <iostream>
Outline using namespace std; using namespace std;
#define SQUARE(x) x * x inline int SQUARE(int x) { return x * x; }
const-ness & int main() { int main() {
cv-qualifier int a = 3, b; int a = 3, b;
const-ness b = SQUARE(a); b = SQUARE(a);
Advantages cout << "Square = " cout << "Square = "
Pointers << b << endl; << b << endl;
volatile return 0; return 0;
} }
inline
functions
Macros Square = 9 Square = 9
inline
Summary • SQUARE(x) is a macro with one param • SQUARE(x) is a function with one param
• Macro SQUARE(x) is efficient • inline SQUARE(x) is equally efficient
• SQUARE(a + 1) fails • SQUARE(a + 1) works
• SQUARE(++a) fails • SQUARE(++a) works
• SQUARE(++a) does not check type • SQUARE(++a) checks type
CS20202: Software Engineering Intructors: Abir Das and Sourangshu Bhattacharya 21
Macros & inline Functions:
Compare and Contrast
Module 06 Macros inline Functions
Intructors: • Expanded at the place of calls • Expanded at the place of calls
Abir Das and • Efficient in execution • Efficient in execution
Sourangshu • Code bloats • Code bloats
Bhattacharya • Has syntactic and semantic pitfalls • No pitfall
• Type checking for parameters is not done • Type checking for parameters is robust
• Helps to write max / swap for all types • Needs template for the same purpose
Objectives & • Errors are not checked during compilation • Errors are checked during compilation
Outline • Not available to debugger • Available to debugger in DEBUG build
const-ness &
cv-qualifier
const-ness
Advantages
Pointers
volatile
inline
functions
Macros
inline
Summary
CS20202: Software Engineering Intructors: Abir Das and Sourangshu Bhattacharya 22
Limitations of Function inlineing
Module 06
Intructors:
inlineing is a directive – compiler may not inline
Abir Das and
Sourangshu
functions with large body
Bhattacharya
inline functions may not be recursive
Objectives &
Outline
Function body is needed for inlineing at the time of
const-ness & function call. Hence, implementation hiding is not
cv-qualifier
const-ness
possible. Implement inline functions in header files
Advantages
Pointers
inline functions must not have two different definitions
volatile
inline
functions
Macros
inline
Summary
CS20202: Software Engineering Intructors: Abir Das and Sourangshu Bhattacharya 23
Module Summary
Module 06
Intructors:
Revisit manifest constants from C
Abir Das and
Sourangshu Understand const-ness, its use and advantages over
Bhattacharya
manifest constants
Objectives &
Outline
Understand the interplay of const and pointer
const-ness & Understand the notion and use of volatile data
cv-qualifier
const-ness
Advantages
Revisit macros with parameters from C
Pointers
volatile
Understand inline functions and their advantages over
inline macros
functions
Macros Limitations of inlineing
inline
Summary
CS20202: Software Engineering Intructors: Abir Das and Sourangshu Bhattacharya 24