// Mathematical operators
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
// A macro to display a string and a value:
#define PRINT(STR, VAR) \
cout << STR " = " << VAR << endl
int main()
{
int i, j, k;
float u, v, w; // Applies to doubles, too
cout << "Enter an integer: ";
cin >> j;
cout << "Enter another integer: ";
cin >> k;
PRINT("j",j); PRINT("k",k);
i = j + k; PRINT("j + k",i);
i = j - k; PRINT("j - k",i);
i = k / j; PRINT("k / j",i);
i = k * j; PRINT("k * j",i);
i = k % j; PRINT("k % j",i);
// The following only works with integers:
j %= k; PRINT("j %= k", j);
cout << "Enter a floating-point number: ";
cin >> v;
cout << "Enter another floating-point number: ";
cin >> w;
PRINT("v",v); PRINT("w",w);
u = v + w; PRINT("v + w", u);
u = v - w; PRINT("v - w", u);
u = v * w; PRINT("v * w", u);
u = v / w; PRINT("v / w", u);
// The following works for ints, chars, and doubles too:
PRINT("u", u); PRINT("v", v);
u += v; PRINT("u += v", u);
u -= v; PRINT("u -= v", u);
u *= v; PRINT("u *= v", u);
u /= v; PRINT("u /= v", u);
return 0;
}
/*
g++ Mathops.cpp -o Mathops
./Mathops
Enter an integer: 1234
Enter another integer: 456789
j = 1234
k = 456789
j + k = 458023
j - k = -455555
k / j = 370
k * j = 563677626
k % j = 209
j %= k = 1234
Enter a floating-point number: 123.456
Enter another floating-point number: 7890.1234
v = 123.456
w = 7890.12
v + w = 8013.58
v - w = -7766.67
v * w = 974083
v / w = 0.0156469
u = 0.0156469
v = 123.456
u += v = 123.472
u -= v = 0.0156479
u *= v = 1.93183
u /= v = 0.0156479
*/
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
// Relational and logical operators
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
int main()
{
int i,j;
cout << "Enter an integer: ";
cin >> i;
cout << "Enter another integer: ";
cin >> j;
cout << "i > j is " << (i > j) << endl;
cout << "i < j is " << (i < j) << endl;
cout << "i >= j is " << (i >= j) << endl;
cout << "i <= j is " << (i <= j) << endl;
cout << "!(i > j) is " << !(i > j) << endl; // i <= j
cout << "i == j is " << (i == j) << endl;
cout << "i != j is " << (i != j) << endl;
cout << "i && j is " << (i && j) << endl;
cout << "i || j is " << (i || j) << endl;
cout << "(i < 10) && (j < 10) is " << ((i < 10) && (j < 10)) << endl;
}
/*
g++ Boolean.cpp -o Boolean
./Boolean
Enter an integer: 0
Enter another integer: 0
i > j is 0 // false
i < j is 0
i >= j is 1 // true
i <= j is 1
!(i > j) is 1 // i <= j
i == j is 1
i != j is 0
i && j is 0
i || j is 0
(i < 10) && (j < 10) is 1
./Boolean
Enter an integer: 1
Enter another integer: 2
i > j is 0
i < j is 1
i >= j is 0
i <= j is 1
!(i > j) is 1 // i <= j
i == j is 0
i != j is 1
i && j is 1
i || j is 1
(i < 10) && (j < 10) is 1
./Boolean
Enter an integer: 10
Enter another integer: 9
i > j is 1
i < j is 0
i >= j is 1
i <= j is 0
!(i > j) is 0 // i <= j
i == j is 0
i != j is 1
i && j is 1
i || j is 1
(i < 10) && (j < 10) is 0
*/
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
Exercise 3-11. Modify Boolean.cpp (previous program) so that it works with double values instead of ints.
// Relational and logical operators
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
int main()
{
double i,j;
cout << "Enter a number: ";
cin >> i;
cout << "Enter another number: ";
cin >> j;
cout << "i > j is " << (i > j) << endl;
cout << "i < j is " << (i < j) << endl;
cout << "i >= j is " << (i >= j) << endl;
cout << "i <= j is " << (i <= j) << endl;
cout << "i == j is " << (i == j) << endl;
cout << "i != j is " << (i != j) << endl;
cout << "i && j is " << (i && j) << endl;
cout << "i || j is " << (i || j) << endl;
cout << "(i < 10) && (j < 10) is " << ((i < 10) && (j < 10)) << endl;
}
/*
g++ BoolDouble.cpp -o BoolDouble
./BoolDouble
Enter a number: 0
Enter another number: 0
i > j is 0 // false
i < j is 0
i >= j is 1 // true
i <= j is 1
i == j is 1
i != j is 0
i && j is 0
i || j is 0
(i < 10) && (j < 10) is 1
./BoolDouble
Enter a number: 0.1
Enter another number: 0.01
i > j is 1
i < j is 0
i >= j is 1
i <= j is 0
i == j is 0
i != j is 1
i && j is 1
i || j is 1
(i < 10) && (j < 10) is 1
./BoolDouble
Enter a number: 1
Enter another number: 1.01
i > j is 0
i < j is 1
i >= j is 0
i <= j is 1
i == j is 0
i != j is 1
i && j is 1
i || j is 1
(i < 10) && (j < 10) is 1
./BoolDouble
Enter a number: 9.999
Enter another number: 9.99
i > j is 1
i < j is 0
i >= j is 1
i <= j is 0
i == j is 0
i != j is 1
i && j is 1
i || j is 1
(i < 10) && (j < 10) is 1
./BoolDouble
Enter a number: 10
Enter another number: 9.999999
i > j is 1
i < j is 0
i >= j is 1
i <= j is 0
i == j is 0
i != j is 1
i && j is 1
i || j is 1
(i < 10) && (j < 10) is 0
*/
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
// Display a byte in binary
void printBinary(const unsigned char val);
// We do not have to include PrintBinary.hpp in this file
#include <iostream>
// Display a byte in binary
void printBinary(const unsigned char val)
{
for(int i = 7; i >= 0; i--)
{ // print bits from first (most significant) to last (least significant)
if(val & (1 << i)) // set (1) bit
{std::cout << "1";} // note the fully qualified cout, std::cout
else {std::cout << "0";} // 0 bit
}
}
/*
g++ -c PrintBinary.cpp // create object file
*/
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
// Demonstration of bit manipulation
#include "PrintBinary.hpp" // for printBinary()
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
// A macro to save typing:
#define PR(STR, EXPR) \
cout << STR; printBinary(EXPR); cout << endl;
int main()
{
unsigned int getval;
unsigned char a, b;
cout << "Enter a number between 0 and 255: ";
cin >> getval; a = getval;
PR("a in binary: ", a) // semicolon not required here
cout << "Enter a number between 0 and 255: ";
cin >> getval; b = getval;
PR("b in binary: ", b)
PR("a | b = ", a | b)
PR("a & b = ", a & b)
PR("a ^ b = ", a ^ b)
PR("~a = ", ~a)
PR("~b = ", ~b)
// An interesting bit pattern:
unsigned char c = 0x5A; // 90
PR("c in binary: ", c)
a |= c;
PR("a |= c; a = ", a)
b &= c;
PR("b &= c; b = ", b)
b ^= a;
PR("b ^= a; b = ", b)
}
/*
g++ -c PrintBinary.cpp Bitwise.cpp // create object files
g++ -c *.cpp
g++ PrintBinary.o Bitwise.o -o Bitwise // link object files, create executable
g++ *.o -o Bitwise
rm *.o // clean (delete object files)
./Bitwise
Enter a number between 0 and 255: 0
a in binary: 00000000
Enter a number between 0 and 255: 255
b in binary: 11111111
a | b = 11111111
a & b = 00000000
a ^ b = 11111111
~a = 11111111
~b = 00000000
c in binary: 01011010
a |= c; a = 01011010
b &= c; b = 01011010
b ^= a; b = 00000000
./Bitwise
Enter a number between 0 and 255: 26
a in binary: 00011010
Enter a number between 0 and 255: 105
b in binary: 01101001
a | b = 01111011
a & b = 00001000
a ^ b = 01110011
~a = 11100101
~b = 10010110
c in binary: 01011010
a |= c; a = 01011010
b &= c; b = 01001000
b ^= a; b = 00010010
*/
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
Exercise 3-13. Modify Bitwise.cpp (from ch3-Bitwise) to use the functions from Rotation.cpp (see below). Make sure you display the results in such a way that it’s clear what’s happening during rotations.
// Perform left and right rotations
// rotate one position to the left:
unsigned char rol(unsigned char val);
// rotate one position to the right:
unsigned char ror(unsigned char val);
// Perform left and right rotations
// rotate one position to the left:
unsigned char rol(unsigned char val)
{
int highbit;
if(val & 0x80) // 0x80 is the high bit only: 10000000
{highbit = 1;}
else {highbit = 0;}
// Left shift (bottom bit becomes 0):
val <<= 1;
// Rotate the high bit onto the bottom:
val |= highbit;
return val;
}
// rotate one position to the right:
unsigned char ror(unsigned char val)
{
int lowbit;
if(val & 1) // Check the low bit: 00000001
{lowbit = 1;}
else {lowbit = 0;}
// Right shift by one position:
val >>= 1; // highest bit becomes 0 (for unsigned)
// Rotate the low bit onto the top:
val |= (lowbit << 7);
return val;
}
/*
g++ -c Rotation.cpp // create object file
*/
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
// Demonstration of bit manipulation
#include "PrintBinary.hpp" // for printBinary()
#include "Rotation.hpp" // for rol(), ror()
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
// A macro to save typing:
#define PR(STR, EXPR) \
cout << STR; printBinary(EXPR); cout << endl;
int main()
{
unsigned int getval;
unsigned char a, b;
cout << "Enter a number between 0 and 255: ";
cin >> getval; a = getval;
PR("rol(a) = ", rol(a)) // semicolon not required here
PR("a in binary: ", a)
PR("ror(a) = ", ror(a))
cout << endl;
cout << "Enter a number between 0 and 255: ";
cin >> getval; b = getval;
PR("rol(b) = ", rol(b))
PR("b in binary: ", b)
PR("ror(b) = ", ror(b))
cout << endl;
PR("rol(a | b) = ", rol(a | b))
PR("a | b = ", a | b)
PR("ror(a | b) = ", ror(a | b))
cout << endl;
PR("rol(a & b) = ", rol(a & b))
PR("a & b = ", a & b)
PR("ror(a & b) = ", ror(a & b))
cout << endl;
PR("rol(a ^ b) = ", rol(a ^ b))
PR("a ^ b = ", a ^ b)
PR("ror(a ^ b) = ", ror(a ^ b))
cout << endl;
PR("rol(~a) = ", rol(~a))
PR("~a = ", ~a)
PR("ror(~a) = ", ror(~a))
cout << endl;
PR("rol(~b) = ", rol(~b))
PR("~b = ", ~b)
PR("ror(~b) = ", ror(~b))
cout << endl;
// An interesting bit pattern:
unsigned char c = 0x5A; // 90
PR("rol(c) = ", rol(c))
PR("c in binary: ", c)
PR("ror(c) = ", ror(c))
cout << endl;
a |= c;
cout << "a |= c;" << endl;
PR("rol(a) = ", rol(a))
PR("a = ", a)
PR("ror(a) = ", ror(a))
cout << endl;
b &= c;
cout << "b &= c;" << endl;
PR("rol(b) = ", rol(b))
PR("b = ", b)
PR("ror(b) = ", ror(b))
cout << endl;
b ^= a;
cout << "b ^= a;" << endl;
PR("rol(b) = ", rol(b))
PR("b = ", b)
PR("ror(b) = ", ror(b))
}
/*
g++ -c PrintBinary.cpp Rotation.cpp Bitwiser.cpp // create object files
g++ -c *.cpp
g++ PrintBinary.o Rotation.o Bitwiser.o -o Bitwiser // link object files,
g++ *.o -o Bitwiser // create executable
rm *.o // clean (delete object files)
./Bitwiser
Enter a number between 0 and 255: 26
rol(a) = 00110100
a in binary: 00011010
ror(a) = 00001101
Enter a number between 0 and 255: 105
rol(b) = 11010010
b in binary: 01101001
ror(b) = 10110100
rol(a | b) = 11110110
a | b = 01111011
ror(a | b) = 10111101
rol(a & b) = 00010000
a & b = 00001000
ror(a & b) = 00000100
rol(a ^ b) = 11100110
a ^ b = 01110011
ror(a ^ b) = 10111001
rol(~a) = 11001011
~a = 11100101
ror(~a) = 11110010
rol(~b) = 00101101
~b = 10010110
ror(~b) = 01001011
rol(c) = 10110100
c in binary: 01011010
ror(c) = 00101101
a |= c;
rol(a) = 10110100
a = 01011010
ror(a) = 00101101
b &= c;
rol(b) = 10010000
b = 01001000
ror(b) = 00100100
b ^= a;
rol(b) = 00100100
b = 00010010
ror(b) = 00001001
*/
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
Exercise 3-14. Modify Ifthen.cpp (Section ch3-Controlling_Execution) to use the ternary if-else operator (?:).
// Demonstration of ternary operator
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
int main()
{
int i;
cout << "Type a number and 'Enter'" << endl;
cin >> i;
(i > 5) ? cout << "It's greater than 5" << endl
: // i <= 5
(i < 5) ? cout << "It's less than 5" << endl
: cout << "It's equal to 5" << endl;
// More formal:
(i > 5) ? cout << "It's greater than 5" << endl
: // i <= 5
(
(i < 5) ? cout << "It's less than 5" << endl
: cout << "It's equal to 5" << endl
);
cout << "Type a number and 'Enter'" << endl;
cin >> i;
(i < 10) ?
(
(i > 5) ? cout << "5 < " << i << " < 10" << endl
: cout << i << " <= 5" << endl
)
: cout << i << " >= 10" << endl;
return 0;
}
/*
g++ Ternary.cpp -o Ternary
./Ternary
Type a number and 'Enter'
1
It's less than 5
It's less than 5
Type a number and 'Enter'
2
2 <= 5
./Ternary
Type a number and 'Enter'
5
It's equal to 5
It's equal to 5
Type a number and 'Enter'
6
5 < 6 < 10
./Ternary
Type a number and 'Enter'
7
It's greater than 5
It's greater than 5
Type a number and 'Enter'
10
10 >= 10
*/
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
#include <iostream>
using std::cout;
using std::endl;
int main()
{
int a = 0, b = 10, c = 20, d = 30, e = 40;
cout << "a = " << a << ", b = " << b << ", c = " << c
<< ", d = " << d << ", e = " << e << endl;
a = (b++, c++, d++, e++); // a = e before incrementation
cout << "a = " << a << ", b = " << b << ", c = " << c
<< ", d = " << d << ", e = " << e << endl;
// The parentheses are critical here. Without
// them, the statement will evaluate to:
a = b++, c++, d++, e++; // a = b before incrementation
cout << "a = " << a << ", b = " << b << ", c = " << c
<< ", d = " << d << ", e = " << e << endl;
(a = b++), c++, d++, e++; // a = b before incrementation
cout << "a = " << a << ", b = " << b << ", c = " << c
<< ", d = " << d << ", e = " << e << endl;
a = (b++, c++), d++, e++; // a = c before incrementation
cout << "a = " << a << ", b = " << b << ", c = " << c
<< ", d = " << d << ", e = " << e << endl;
return 0;
}
/*
g++ CommaOperator.cpp -o CommaOperator
./CommaOperator
a = 0, b = 10, c = 20, d = 30, e = 40
a = 40, b = 11, c = 21, d = 31, e = 41
a = 11, b = 12, c = 22, d = 32, e = 42
a = 12, b = 13, c = 23, d = 33, e = 43
a = 23, b = 14, c = 24, d = 34, e = 44
*/
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
#include <stdio.h> // for printf()
#include <unistd.h> // for sleep()
int main()
{
int a = 1, b = 1;
while (a == b) // correct
{
printf("a = %d, b = %d\n", a, b);
b++; sleep(1); // pause for 1 second
}
printf("Out of while1\n");
while (a = b) // instead of while (a == b)
{ // exits when b == 0
printf("a = %d, b = %d\n", a, b);
b--; sleep(1); // pause for 1 second
}
printf("Out of while2\n");
while (a = b) // instead of while (a == b)
{ // exits immediately as b == 0
printf("a = %d, b = %d\n", a, b); // never gets here
b++; sleep(1); // pause for 1 second
}
printf("Out of while3\n");
b++; // b = 1;
while (a = b) // instead of while (a == b)
{ // starts with b == 1
printf("a = %d, b = %d\n", a, b);
b++; sleep(1); // pause for 1 second
} // never exits while4
printf("Out of while4\n"); // never gets here
return 0;
}
/*
gcc pitfall.c -o pitfall
./pitfall
a = 1, b = 1
Out of while1
a = 2, b = 2
a = 1, b = 1
Out of while2
Out of while3
a = 1, b = 1
a = 2, b = 2
a = 3, b = 3
a = 4, b = 4
a = 5, b = 5
a = 6, b = 6
a = 7, b = 7
a = 8, b = 8
^C // Ctrl^C
*/
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
#include <cstdio> // for printf()
#include <unistd.h> // for sleep()
int main()
{
int a = 1, b = 1;
while (a == b) // correct
{
printf("a = %d, b = %d\n", a, b);
b++; sleep(1); // pause for 1 second
}
printf("Out of while1\n");
while (a = b) // instead of while (a == b)
{ // exits when b == 0
printf("a = %d, b = %d\n", a, b);
b--; sleep(1); // pause for 1 second
}
printf("Out of while2\n");
while (a = b) // instead of while (a == b)
{ // exits immediately as b == 0
printf("a = %d, b = %d\n", a, b); // never gets here
b++; sleep(1); // pause for 1 second
}
printf("Out of while3\n");
b++; // b = 1;
while (a = b) // instead of while (a == b)
{ // starts with b == 1
printf("a = %d, b = %d\n", a, b);
b++; sleep(1); // pause for 1 second
} // never exits while4
printf("Out of while4\n"); // never gets here
return 0;
}
/*
g++ Pitfall.cpp -o Pitfall
./Pitfall
a = 1, b = 1
Out of while1
a = 2, b = 2
a = 1, b = 1
Out of while2
Out of while3
a = 1, b = 1
a = 2, b = 2
a = 3, b = 3
a = 4, b = 4
a = 5, b = 5
a = 6, b = 6
a = 7, b = 7
a = 8, b = 8
^C // Ctrl^C
*/
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
#include <stdio.h> // for printf()
int main()
{
int i = 200;
unsigned long ul = (unsigned long int)i; // explicit cast
long long ll = i; // implicit cast from int to long long
unsigned char uc = ll; // implicit cast from long long to unsigned char
short sh = ll; // implicit cast (restrictive) from long long to short int
printf("sizeof(unsigned char) = %lu, sizeof(uc) = %lu\n",
sizeof(unsigned char), sizeof(uc));
printf("sizeof(short) = %lu, sizeof(sh) = %lu\n",
sizeof(short), sizeof(sh));
printf("sizeof(int) = %lu, sizeof(i) = %lu\n", sizeof(int), sizeof(i));
printf("sizeof(unsigned long) = %lu, sizeof(ul) = %lu\n",
sizeof(unsigned long), sizeof(ul));
printf("sizeof(long long) = %lu, sizeof(ll) = %lu\n",
sizeof(long long), sizeof(ll));
// Function call cast only works in C++:
// float f1 = float(200); // compile error in C
// This is equivalent to:
float f2 = (float)200; // C style cast
float f3 = 200.f; // 200f gives a compile error
float f4 = 200; // implicit cast from int to float
double d = f2; // implicit cast from float to double
long double ld = 200; // implicit cast from int to long double
float f5 = ld; // implicit cast (restrictive) from long double to float
printf("sizeof(float) = %lu, sizeof(f5) = %lu\n",
sizeof(float), sizeof(f5));
printf("sizeof(double) = %lu, sizeof(d) = %lu\n",
sizeof(double), sizeof(d));
printf("sizeof(long double) = %lu, sizeof(ld) = %lu\n",
sizeof(long double), sizeof(ld));
return 0;
}
/*
gcc simplecast.c -o simplecast
./simplecast
sizeof(unsigned char) = 1, sizeof(uc) = 1
sizeof(short) = 2, sizeof(sh) = 2
sizeof(int) = 4, sizeof(i) = 4
sizeof(unsigned long) = 8, sizeof(ul) = 8
sizeof(long long) = 8, sizeof(ll) = 8
sizeof(float) = 4, sizeof(f5) = 4
sizeof(double) = 8, sizeof(d) = 8
sizeof(long double) = 16, sizeof(ld) = 16
*/
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
#include <iostream>
using std::cout;
using std::endl;
int main()
{
int i = 200;
unsigned long ul = (unsigned long int)i; // explicit cast
long long ll = i; // implicit cast from int to long long
unsigned char uc = ll; // implicit cast from long long to unsigned char
short sh = ll; // implicit cast (restrictive) from long long to short int
cout << "sizeof(unsigned char) = " << sizeof(unsigned char)
<< ", sizeof(uc) = " << sizeof(uc) << endl;
cout << "sizeof(short) = " << sizeof(short)
<< ", sizeof(sh) = " << sizeof(sh) << endl;
cout << "sizeof(int) = " << sizeof(int)
<< ", sizeof(i) = " << sizeof(i) << endl;
cout << "sizeof(unsigned long) = " << sizeof(unsigned long)
<< ", sizeof(ul) = " << sizeof(ul) << endl;
cout << "sizeof(long long) = " << sizeof(long long)
<< ", sizeof(ll) = " << sizeof(ll) << endl;
float f1 = float(200); // C++ style cast, function call cast
// This is equivalent to:
float f2 = (float)200; // C style cast
float f3 = 200.f; // 200f gives a compile error
float f4 = 200; // implicit cast from int to float
double d = f1; // implicit cast from float to double
long double ld = 200; // implicit cast from int to long double
float f5 = ld; // implicit cast (restrictive) from long double to float
cout << "sizeof(float) = " << sizeof(float)
<< ", sizeof(f5) = " << sizeof(f5) << endl;
cout << "sizeof(double) = " << sizeof(double)
<< ", sizeof(d) = " << sizeof(d) << endl;
cout << "sizeof(long double) = " << sizeof(long double)
<< ", sizeof(ld) = " << sizeof(ld) << endl;
return 0;
}
/*
g++ SimpleCast.cpp -o SimpleCast
./SimpleCast
sizeof(unsigned char) = 1, sizeof(uc) = 1
sizeof(short) = 2, sizeof(sh) = 2
sizeof(int) = 4, sizeof(i) = 4
sizeof(unsigned long) = 8, sizeof(ul) = 8
sizeof(long long) = 8, sizeof(ll) = 8
sizeof(float) = 4, sizeof(f5) = 4
sizeof(double) = 8, sizeof(d) = 8
sizeof(long double) = 16, sizeof(ld) = 16
*/
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
#include <stdio.h> // for printf()
void func(int i) {}
int main()
{
int i = 0x7fff; // 0x00007fff (32767)
long l;
float f;
// (1) Typical castless conversions:
l = i;
f = i;
// Also works:
l = (long)i; // explicit cast
f = (float)i; // explicit cast
// (2) Narrowing conversions:
i = l; // May lose digits (automatic narrowing cast)
i = f; // May lose info (automatic narrowing cast)
// Says "I know," eliminates warnings:
i = (int)l; // narrowing cast
i = (float)f; // narrowing cast
char c = (char)i; // 0xff, last byte of i: 11111111 (narrowing cast)
c = i; // automatic narrowing cast
printf("i = %d\n", i); // 32767
printf("(int)c = %d\n", (int)c); // -1 (binary 11111111)
printf("(unsigned int)c = %u\n", (unsigned int)c); // UINT_MAX (limits.h)
unsigned char uc = i; // 0xff, last byte of i (automatic narrowing cast)
printf("(int)uc = %d\n", (int)uc); // 255, binary 11111111 (CHAR_MAX)
// (3) Forcing a conversion from void* :
void* vp = &i;
float* fp = (float*)vp; // dangerous conversion
// (4) Implicit type conversions, normally performed by the compiler:
double d = 0.0;
int x = d; // Automatic type conversion (narrowing)
x = (int)d; // More explicit
func(d); // Automatic type conversion (narrowing)
func((int)d); // More explicit
}
/*
gcc staticast.c -o staticast
./staticast
i = 32767
(int)c = -1
(unsigned int)c = 4294967295 // UINT_MAX
(int)uc = 255 // CHAR_MAX
*/
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
#include <iostream>
using std::cout;
using std::endl;
void func(int) {} // C requires a named parameter, as in `int i'
int main()
{
int i = 0x7fff; // 0x00007fff (32767)
long l;
float f;
// (1) Typical castless conversions:
l = i;
f = i;
// Also works:
l = static_cast<long>(i);
l = (long)i; // C style cast
f = static_cast<float>(i);
f = (float)i; // C style cast
// (2) Narrowing conversions:
i = l; // May lose digits (automatic narrowing cast)
i = f; // May lose info (automatic narrowing cast)
// Says "I know," eliminates warnings:
i = static_cast<int>(l);
i = (int)l; // C style cast (narrowing)
i = static_cast<int>(f);
i = (float)f; // C style cast (narrowing)
char c = static_cast<char>(i); // 0xff, last byte of i: 11111111
cout << "i = " << i << endl; // 32767
cout << "(int)c = " << (int)c << endl; // -1 (binary 11111111)
cout << "(unsigned int)c = " << (unsigned int)c << endl; // UINT_MAX
c = (char)i; // C style cast (narrowing)
c = i; // automatic narrowing cast
unsigned char uc = i; // 0xff (255), last byte of i: 11111111
cout << "(int)uc = " << (int)uc << endl; // 255 (CHAR_MAX, see <climits>)
// (3) Forcing a conversion from void* :
void* vp = &i;
// Old way produces a dangerous conversion:
float* fp = (float*)vp;
// The new way is equally dangerous:
fp = static_cast<float*>(vp);
// (4) Implicit type conversions, normally performed by the compiler:
double d = 0.0;
int x = d; // Automatic type conversion (narrowing)
x = static_cast<int>(d); // More explicit
x = (int)d; // C style cast
func(d); // Automatic type conversion (narrowing)
func(static_cast<int>(d)); // More explicit
func((int)d); // More explicit, C style
}
/*
g++ StaticCast.cpp -o StaticCast
./StaticCast
i = 32767
(int)c = -1
(unsigned int)c = 4294967295 // UINT_MAX
(int)uc = 255 // CHAR_MAX
*/
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
int main()
{
const int i = 0;
int* j = (int*)&i;
long* l = (long*)&i;
volatile int k = 0;
int* u = (int*)&k;
k = (int)i;
const int* v = (const int*)&k;
const int * const w = (const int*)&k;
}
/*
gcc constcast.c -o constcast
./constcast
*/
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
int main()
{
const int i = 0;
int* j = (int*)&i; // Deprecated form (C style cast)
j = const_cast<int*>(&i); // Preferred form
// Can't do simultaneous additional casting:
// long* l = const_cast<long*>(&i); // compile error
long* l = (long*)&i; // C style works
volatile int k = 0;
int* u = const_cast<int*>(&k);
u = (int*)&k; // C style works too
// k = const_cast<int>(i); // compile error: not pointer or reference
k = (int)i; // C style works
const int* v = const_cast<const int*>(&k);
v = (const int*)&k; // C style
const int * const w = const_cast<const int*>(&k);
// w = (const int*)&k; // compile error: cannot change constant pointer w
}
/*
g++ ConstCast.cpp -o ConstCast
./ConstCast
*/
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
#include <stdio.h> // for printf()
#define SIZE 10
struct X { int a[SIZE]; };
void print(struct X* x);
int main()
{
struct X x;
print(&x);
int* xp = (int*)&x;
int* ip;
for(ip = xp; ip < xp + SIZE; ip++)
{*ip = 0;}
// Can't use xp as an X* at this point unless you cast it back:
// print(xp); // compile error: xp is int*, not struct X*
print((struct X*)xp);
// In this example, you can also just use the original identifier:
print(&x);
}
void print(struct X* x)
{
int i;
for(i = 0; i < SIZE; i++)
{printf("%d ", x->a[i]);}
printf("\n--------------------\n");
}
/*
gcc reinterpretcast.c -o reinterpretcast
./reinterpretcast
-2015726872 32650 755405424 21993 0 0 755404960 21993 2081284944 32766
--------------------
0 0 0 0 0 0 0 0 0 0
--------------------
0 0 0 0 0 0 0 0 0 0
--------------------
*/
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
#include <iostream>
using std::cout;
using std::endl;
const int sz = 10;
struct X { int a[sz]; };
void print(X* x);
int main()
{
X x;
print(&x);
int* xp = reinterpret_cast<int*>(&x);
xp = (int*)&x; // C style cast
for(int* i = xp; i < xp + sz; i++)
{*i = 0;}
// Can't use xp as an X* at this point unless you cast it back:
// print(xp); // compile error: xp is int*, not X*
print(reinterpret_cast<X*>(xp));
print(reinterpret_cast<struct X*>(xp)); // C requires `struct' here
print((X*)xp); // C style cast
print((struct X*)xp); // C requires `struct' here
// In this example, you can also just use the original identifier:
print(&x);
}
void print(X* x)
{
for(int i = 0; i < sz; i++)
{cout << x->a[i] << ' ';}
cout << endl << "--------------------" << endl;
}
/*
g++ ReinterpretCast.cpp -o ReinterpretCast
./ReinterpretCast
1926591208 32517 -1017302112 21856 0 0 -1017302752 21856 -1467862800 32764
--------------------
0 0 0 0 0 0 0 0 0 0
--------------------
0 0 0 0 0 0 0 0 0 0
--------------------
0 0 0 0 0 0 0 0 0 0
--------------------
0 0 0 0 0 0 0 0 0 0
--------------------
0 0 0 0 0 0 0 0 0 0
--------------------
*/
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
Exercise 3-8. Write a program that uses all the trigraphs to see if your compiler supports them.
%:include <stdio.h> // for printf()
int main()
<%
char hello<::> = "Hello!";
printf("%s\n", hello);
return 0;
%>
/*
gcc digraphs.c -o digraphs // compiles directly
./digraphs
Hello!
*/
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
%:include <iostream>
using std::cout;
using std::endl;
int main()
<%
char hello<::> = "Hello!";
cout << hello << endl;
return 0;
%>
/*
g++ Digraphs.cpp -o Digraphs // compiles directly
./Digraphs
Hello!
*/
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
??=include <stdio.h> // for printf()
int main()
??<
printf("Trigraphs in C:??/n");
printf("??/???/?=??/t??=??/n");
printf("??/???/?/??/t??/??/??/n");
printf("??/???/?'??/t??'??/n");
printf("??/???/?(??/t??(??/n");
printf("??/???/?)??/t??)??/n");
printf("??/???/?!??/t??!??/n");
printf("??/???/?<??/t??<??/n");
printf("??/???/?>??/t??>??/n");
printf("??/???/?-??/t??-??/n");
return 0;
??>
/*
gcc trigraphs.c -trigraphs -o trigraphs // needs option -trigraphs to compile
./trigraphs
Trigraphs in C:
??= #
??/ \
??' ^
??( [
??) ]
??! |
??< {
??> }
??- ~
*/
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
??=include <iostream>
using std::cout;
using std::endl;
int main()
??<
cout << "Trigraphs in C++:" << endl;
cout << "??/???/?=??/t??=" << endl;
cout << "??/???/?/??/t??/??/" << endl;
cout << "??/???/?'??/t??'" << endl;
cout << "??/???/?(??/t??(" << endl;
cout << "??/???/?)??/t??)" << endl;
cout << "??/???/?!??/t??!" << endl;
cout << "??/???/?<??/t??<" << endl;
cout << "??/???/?>??/t??>" << endl;
cout << "??/???/?-??/t??-" << endl;
return 0;
??>
/*
g++ Trigraphs.cpp -trigraphs -o Trigraphs // needs option -trigraphs to compile
./Trigraphs
Trigraphs in C++:
??= #
??/ \
??' ^
??( [
??) ]
??! |
??< {
??> }
??- ~
*/
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
Exercise 3-12. Modify Boolean.cpp and Bitwise.cpp (ch3-Bitwise, Section ch3-Operators) so they use the explicit operators (if your compiler is conformant to the C++ Standard it will support these).
// Relational and logical explicit operators
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
int main()
{
int i,j;
cout << "Enter an integer: ";
cin >> i;
cout << "Enter another integer: ";
cin >> j;
cout << "i > j is " << (i > j) << endl;
cout << "i < j is " << (i < j) << endl;
cout << "i >= j is " << (i >= j) << endl;
cout << "i <= j is " << (i <= j) << endl;
cout << "not(i > j) is " << not(i > j) << endl; // i <= j
cout << "i == j is " << (i == j) << endl;
cout << "i not_eq j is " << (i not_eq j) << endl;
cout << "i and j is " << (i and j) << endl;
cout << "i or j is " << (i or j) << endl;
cout << "(i < 10) and (j < 10) is " << ((i < 10) and (j < 10)) << endl;
}
/*
g++ ExBoolean.cpp -o ExBoolean
./ExBoolean
Enter an integer: 0
Enter another integer: 0
i > j is 0 // false
i < j is 0
i >= j is 1 // true
i <= j is 1
not(i > j) is 1 // i <= j
i == j is 1
i not_eq j is 0
i and j is 0
i or j is 0
(i < 10) and (j < 10) is 1
./ExBoolean
Enter an integer: 1
Enter another integer: 2
i > j is 0
i < j is 1
i >= j is 0
i <= j is 1
not(i > j) is 1 // i <= j
i == j is 0
i not_eq j is 1
i and j is 1
i or j is 1
(i < 10) and (j < 10) is 1
./ExBoolean
Enter an integer: 10
Enter another integer: 9
i > j is 1
i < j is 0
i >= j is 1
i <= j is 0
not(i > j) is 0 // i <= j
i == j is 0
i not_eq j is 1
i and j is 1
i or j is 1
(i < 10) and (j < 10) is 0
*/
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
// Demonstration of bit manipulation with explicit operators
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
void printBinary(const unsigned char val); // Display a byte in binary
// A macro to save typing:
#define PR(STR, EXPR) \
cout << STR; printBinary(EXPR); cout << endl;
int main()
{
unsigned int getval;
unsigned char a, b;
cout << "Enter a number between 0 and 255: ";
cin >> getval; a = getval;
PR("a in binary: ", a) // semicolon not required here
cout << "Enter a number between 0 and 255: ";
cin >> getval; b = getval;
PR("b in binary: ", b)
PR("a bitor b = ", a bitor b)
PR("a bitand b = ", a bitand b)
PR("a xor b = ", a xor b)
PR("compl a = ", compl a)
PR("compl(b) = ", compl(b))
// An interesting bit pattern:
unsigned char c = 0x5A; // 90
PR("c in binary: ", c)
a or_eq c;
PR("a or_eq c; a = ", a)
b and_eq c;
PR("b and_eq c; b = ", b)
b xor_eq a;
PR("b xor_eq a; b = ", b)
}
// Display a byte in binary
void printBinary(const unsigned char val)
{
for(int i = 7; i >= 0; i--)
{ // print bits from first (most significant) to last (least significant)
if(val bitand (1 << i)) // set (1) bit
{cout << "1";}
else {cout << "0";} // 0 bit
}
}
/*
g++ ExBitwise.cpp -o ExBitwise
./ExBitwise
Enter a number between 0 and 255: 0
a in binary: 00000000
Enter a number between 0 and 255: 255
b in binary: 11111111
a bitor b = 11111111
a bitand b = 00000000
a xor b = 11111111
compl a = 11111111
compl(b) = 00000000
c in binary: 01011010
a or_eq c; a = 01011010
b and_eq c; b = 01011010
b xor_eq a; b = 00000000
./ExBitwise
Enter a number between 0 and 255: 26
a in binary: 00011010
Enter a number between 0 and 255: 105
b in binary: 01101001
a bitor b = 01111011
a bitand b = 00001000
a xor b = 01110011
compl a = 11100101
compl(b) = 10010110
c in binary: 01011010
a or_eq c; a = 01011010
b and_eq c; b = 01001000
b xor_eq a; b = 00010010
*/