#include <iostream>
#include <climits> // for CHAR_MIN, CHAR_MAX, UCHAR_MAX
using std::cout;
using std::endl;
int main()
{
char c = 127; // CHAR_MAX (limits.h or climits)
unsigned char uc = 255; // UCHAR_MAX
cout << "c = " << (int)c << endl;
cout << "CHAR_MAX = " << CHAR_MAX << endl;
cout << "++c = " << (int)++c << endl; // CHAR_MIN (modulo 2 arithmetic)
cout << "CHAR_MIN = " << CHAR_MIN << endl;
cout << "--c = " << (int)--c << endl; // CHAR_MAX (no warning)
cout << "uc = " << (int)uc << endl;
cout << "UCHAR_MAX = " << UCHAR_MAX << endl;
cout << "++uc = " << (int)++uc << endl; // 0 (modulo 2 arithmetic)
cout << "--uc = " << (int)--uc << endl; // UCHAR_MAX (no warning)
c = 1234; // warning: overflow
cout << "c = " << (int)c << endl; // -46
uc = -1234; // warning: unsigned conversion (overflow or underflow)
cout << "uc = " << (int)uc << endl; // 46
uc = -46; // no warning
cout << "uc = " << (int)uc << endl; // 210
return 0;
}
/*
g++ Char.cpp -o Char
./Char
c = 127
CHAR_MAX = 127
++c = -128
CHAR_MIN = -128
--c = 127
uc = 255
UCHAR_MAX = 255
++uc = 0
--uc = 255
c = -46
uc = 46
uc = 210
*/
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
#include <iostream>
using std::cout;
using std::endl;
int main()
{
bool b = false;
cout << "b = " << b << endl; // 0
cout << "++b = " << ++b << endl; // warning: deprecated, displays 1
cout << "++b = " << ++b << endl; // warning: deprecated, still 1
// cout << "--b = " << --b << endl; // compile error
b = 2; // no warning
cout << "b = " << b << endl; // still 1
b = -1; // no warning
cout << "b = " << b << endl; // still 1
cout << "++b = " << ++b << endl; // warning: deprecated, prints 1
return 0;
}
/*
g++ Bool.cpp -o Bool
./Bool
b = 0
++b = 1
++b = 1
b = 1
b = 1
++b = 1
*/
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
#include <iostream>
using std::cout;
using std::endl;
int main()
{
char c;
unsigned char cu;
int i;
unsigned int iu;
short int is;
short iis; // Same as short int
unsigned short int isu;
unsigned short iisu;
long int il;
long iil; // Same as long int
unsigned long int ilu;
unsigned long iilu;
long long int ill;
unsigned long long int illu;
float f;
double d;
long double ld;
cout << "sizeof(char) = " << sizeof(char) << " = " << sizeof(c) << endl;
cout << "sizeof(unsigned char) = " << sizeof(unsigned char)
<< " = " << sizeof(cu) << endl;
cout << "sizeof(int) = " << sizeof(int) << " = " << sizeof(i) << endl;
cout << "sizeof(unsigned int) = " << sizeof(unsigned int)
<< " = " << sizeof(iu) << endl;
cout << "sizeof(short) = " << sizeof(short) << " = " << sizeof(is) << endl;
cout << "sizeof(unsigned short) = " << sizeof(unsigned short)
<< " = " << sizeof(isu) << endl;
cout << "sizeof(long) = " << sizeof(long) << " = " << sizeof(il) << endl;
cout << "sizeof(unsigned long) = " << sizeof(unsigned long)
<< " = " << sizeof(ilu) << endl;
cout << "sizeof(long long) = " << sizeof(long long)
<< " = " << sizeof(ill) << endl;
cout << "sizeof(unsigned long long) = " << sizeof(unsigned long long)
<< " = " << sizeof(illu) << endl;
cout << "sizeof(float) = " << sizeof(float) << " = " << sizeof(f) << endl;
cout << "sizeof(double) = " << sizeof(double) << " = " << sizeof(d) << endl;
cout << "sizeof(long double) = " << sizeof(long double)
<< " = " << sizeof(ld) << endl;
return 0;
}
/*
g++ sizeof.cpp -o sizeof
./sizeof
sizeof(char) = 1 = 1
sizeof(unsigned char) = 1 = 1
sizeof(int) = 4 = 4
sizeof(unsigned int) = 4 = 4
sizeof(short) = 2 = 2
sizeof(unsigned short) = 2 = 2
sizeof(long) = 8 = 8
sizeof(unsigned long) = 8 = 8
sizeof(long long) = 8 = 8
sizeof(unsigned long long) = 8 = 8
sizeof(float) = 4 = 4
sizeof(double) = 8 = 8
sizeof(long double) = 16 = 16
*/
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
#include <iostream>
using std::cout;
using std::endl;
int dog, cat, bird, fish; // global vars initialized to 0
int main(); // can be declared before its definition
void f(int pet); // defined after main()
void g(void){} // defined before main()
int main()
{
int i, j, k;
cout << "sizeof(int): " << sizeof(int) << endl;
cout << "f():\t" << (long)&f << endl;
cout << "g():\t" << (long)&g << endl;
cout << "dog:\t" << (long)&dog << endl;
cout << "cat:\t" << (long)&cat << endl;
cout << "bird:\t" << (long)&bird << endl;
cout << "fish:\t" << (long)&fish << endl;
cout << "main():\t" << (long)&main << endl;
cout << "i:\t" << (long)&i << endl;
cout << "j:\t" << (long)&j << endl;
cout << "k:\t" << (long)&k << endl;
f(dog), f(cat), f(bird), f(fish), g(); // multiple function calls on one line
return 0;
}
void f(int pet)
{
cout << "pet id number: " << pet << endl;
}
/*
g++ YourPets.cpp -o YourPets
./YourPets
sizeof(int): 4
f(): 94641376949411 // f() defined after main()
g(): 94641376948745 // g() defined before main()
dog: 94641376960852
cat: 94641376960856
bird: 94641376960860
fish: 94641376960864
main(): 94641376948756 // after g(), before f()
i: 140721441130380
j: 140721441130384
k: 140721441130388
pet id number: 0 // f(dog)
pet id number: 0 // f(cat)
pet id number: 0 // f(bird)
pet id number: 0 // f(fish)
*/
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
Exercise 3-6. Modify YourPets2.cpp (see YourPets.cpp) so that it uses various different data types (char, int, float, double, and their variants). Run the program and create a map of the resulting memory layout. If you have access to more than one kind of machine, operating system, or compiler, try this experiment with as many variations as you can manage.
// tested in Lubuntu Linux
#include <iostream>
using std::cout;
using std::endl;
char canary;
unsigned char parrot;
short pup;
unsigned short puppy;
int cat;
unsigned dog;
long lizard;
unsigned long grassLizard;
long long snake;
unsigned long long python;
float bird;
double fish;
long double pony, horse;
// void f(); // cannot take the address of an undefined function
void f1 (void) {}
void f2 (int pet)
{
cout << "pet id number: " << pet << endl;
}
int f3 (int) {return 0;}
int f4 (int, int) {return 0;}
int f5 (int, int) {return 0;}
int main()
{
char c;
unsigned char cu;
short sh;
unsigned short shu;
int i;
unsigned iu;
long l;
unsigned long lu;
long long ll;
unsigned long long llu;
float f;
double d;
long double ld1, ld2;
cout << "f1(): " << (long)&f1 << endl; // 11 bytes
cout << "f2(): " << (long)&f2 << endl; // longest definition (74 bytes)
cout << "f3(): " << (long)&f3 << endl; // 18 bytes
cout << "f4(): " << (long)&f4 << endl; // 21 bytes
cout << "f5(): " << (long)&f5 << endl; // same as f4()
cout << endl;
cout << "canary: " << (long)&canary << endl; // 1 byte (char)
cout << "parrot: " << (long)&parrot << endl; // 1 byte (unsigned char)
cout << "pup: " << (long)&pup << endl; // 2 bytes (short)
cout << "puppy: " << (long)&puppy << endl; // 2 bytes (unsigned short)
cout << "cat: " << (long)&cat << endl; // 4 bytes (int)
cout << "dog: " << (long)&dog << endl; // 4 bytes (unsigned int)
cout << "lizard: " << (long)&lizard << endl; // 8 bytes (long)
cout << "grassLizard: " << (long)&grassLizard << endl; // 8B (UL)
cout << "snake: " << (long)&snake << endl; // 8 bytes (long long)
cout << "python: " << (long)&python << endl; // 8 bytes (ULL)
cout << "bird: " << (long)&bird << endl; // global float (8B) aligned
cout << "fish: " << (long)&fish << endl; // as expected, 8 bytes (double)
cout << "pony: " << (long)&pony << endl; // 16 bytes (long double)
cout << "horse: " << (long)&horse << endl; // same as pony
cout << endl;
cout << "c: " << (long)&c << endl; // 1 byte (char)
cout << "cu: " << (long)&cu << endl; // 1 byte (unsigned char)
cout << "sh: " << (long)&sh << endl; // 2 bytes (short)
cout << "shu: " << (long)&shu << endl; // 2 bytes (unsigned short)
cout << "i: " << (long)&i << endl; // 4 bytes (int)
cout << "iu: " << (long)&iu << endl; // 4 bytes (unsigned int)
cout << "f: " << (long)&f << endl; // local float (4B) is aligned here,
cout << "l: " << (long)&l << endl; // although defined after `llu'
cout << "lu: " << (long)&lu << endl; // 8 bytes, (unsigned) long
cout << "ll: " << (long)&ll << endl; // 8 bytes (long long)
cout << "llu: " << (long)&llu << endl; // 8 bytes (ULL)
cout << "d: " << (long)&d << endl; // 8 bytes (double)
cout << "ld1: " << (long)&ld1 << endl; // 16 bytes (long double)
cout << "ld2: " << (long)&ld2 << endl; // same as ld1
return 0;
}
/*
g++ Pets.cpp -o Pets
./Pets
f1(): 94899903296009
f2(): 94899903296020
f3(): 94899903296094
f4(): 94899903296112
f5(): 94899903296133
canary: 94899903308128
parrot: 94899903308129
pup: 94899903308130
puppy: 94899903308132
cat: 94899903308136
dog: 94899903308140
lizard: 94899903308144
grassLizard: 94899903308152
snake: 94899903308160
python: 94899903308168
bird: 94899903308176
fish: 94899903308184
pony: 94899903308192
horse: 94899903308208
c: 140733349822726
cu: 140733349822727
sh: 140733349822728
shu: 140733349822730
i: 140733349822732
iu: 140733349822736
f: 140733349822740
l: 140733349822744
lu: 140733349822752
ll: 140733349822760
llu: 140733349822768
d: 140733349822776
ld1: 140733349822784
ld2: 140733349822800
*/
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
#include <iostream>
using std::cout;
using std::endl;
void f(int a);
int main()
{
int x = 47;
cout << "x = " << x << endl; // 47
f(x); // pass `x' by value
cout << "x = " << x << endl; // 47
return 0;
}
void f(int a)
{
cout << "a = " << a << endl;
a = 5;
cout << "a = " << a << endl;
}
/*
g++ PassByValue.cpp -o PassByValue
./PassByValue
x = 47
a = 47
a = 5
x = 47
*/
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
#include <iostream>
using std::cout;
using std::endl;
void f(int* p);
int main()
{
int x = 47;
cout << "x = " << x << endl; // value of `x'
cout << "&x = " << &x << endl; // address of `x'
f(&x); // &x is a pointer to x (passed by reference)
cout << "x = " << x << endl; // value changed
cout << "&x = " << &x << endl; // address did not change
return 0;
}
void f(int* p)
{
cout << "p = " << p << endl; // address (value of p)
cout << "*p = " << *p << endl; // underlying value
*p = 5; // modify the underlying value that `p' point to
cout << "p = " << p << endl; // address does not change
cout << "*p = " << *p << endl; // underlying value changes
}
/*
g++ PassAddress.cpp -o PassAddress
./PassAddress
x = 47
&x = 0x7ffd1f270084
p = 0x7ffd1f270084
*p = 47
p = 0x7ffd1f270084
*p = 5
x = 5
&x = 0x7ffd1f270084
*/
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
#include <iostream>
using std::cout;
using std::endl;
void f(int& r); // only in C++, does not work in C
int main()
{
int x = 47;
cout << "x = " << x << endl; // value
cout << "&x = " << &x << endl; // address
f(x); // Looks like pass-by-value, is actually pass by reference
cout << "x = " << x << endl; // value changed
cout << "&x = " << &x << endl; // address did not change
return 0;
}
void f(int& r)
{
cout << "r = " << r << endl; // value
cout << "&r = " << &r << endl; // address
r = 5; // value changes
cout << "r = " << r << endl;
cout << "&r = " << &r << endl; // address remains the same
}
/*
g++ PassReference.cpp -o PassReference
./PassReference
x = 47
&x = 0x7ffe4ad4bab4
r = 47
&r = 0x7ffe4ad4bab4
r = 5
&r = 0x7ffe4ad4bab4
x = 5
&x = 0x7ffe4ad4bab4
*/
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
Exercise 3-7. Create two functions, one that takes a string* and one that takes a string& as argument. Each of these functions should modify the outside string object in its own unique way. In main(), create and initialize a string object, print it, then pass it to each of the two functions, printing the results.
#include <iostream>
#include <string>
using std::string;
using std::cout;
using std::endl;
void passByValue(string);
void passAddress(string*);
void passReference(string&);
int main()
{
string str = "Hello!";
cout << str << endl; // Hello!
passByValue(str); // Howdy!
cout << str << endl; // Hello!
passAddress(&str); // Hi!
cout << str << endl; // Hi!
passReference(str); // Halo!
cout << str << endl; // Halo!
return 0;
}
void passByValue(string s)
{
s = "Howdy!";
cout << s << endl;
}
void passAddress(string* sp)
{
*sp = "Hi!";
cout << *sp << endl;
}
void passReference(string& sr)
{
sr = "Halo!";
cout << sr << endl;
}
/*
g++ Strings.cpp -o Strings
./Strings
Hello!
Howdy!
Hello!
Hi!
Hi!
Halo!
Halo!
*/
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
// All possible combinations of basic data types,
// specifiers, pointers and references (as modifiers)
void f1(char c, int i, float f, double d);
void f2(short int si, long int li, long long int lli, long double ld);
void f3(unsigned char uc, unsigned short int usi, unsigned int ui,
unsigned long int uli, unsigned long long int ulli);
void f4(char* cp, int* ip, float* fp, double* dp);
void f5(short int* sip, long int* lip, long long int* llip, long double* ldp);
void f6(unsigned char* ucp, unsigned short int* usip, unsigned int* uip,
unsigned long int* ulip, unsigned long long int* ullip);
void f7(char& cr, int& ir, float& fr, double& dr);
void f8(short int& sir, long int& lir, long long int& llir, long double& ldr);
void f9(unsigned char& ucr, unsigned short int& usir, unsigned int& uir,
unsigned long int& ulir, unsigned long long int& ullir);
int main()
{
return 0;
}
/*
g++ AllDefinitions.cpp -o AllDefinitions
./AllDefinitions
*/
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
int main()
{
void* vp;
char c;
int i;
float f;
double d;
// The address of ANY type can be assigned to a void pointer:
vp = &c; // no cast required
vp = &i;
vp = &f;
vp = &d;
return 0;
}
/*
g++ VoidPointer.cpp -o VoidPointer
./VoidPointer
*/
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
#include <iostream>
using std::cout;
using std::endl;
int main()
{
int i = 99;
void* vp = &i;
// cout << "i = " << i << ", *vp = " << // Can't dereference a void pointer:
// *vp << endl; // Compile error: `void*' is not a pointer-to-object type
cout << "i = " << i << ", *((int*)vp) = " <<
*((int*)vp) << endl; // Must cast back to `int*' before dereferencing
// *vp = 3; // Compile-time error: `void*' is not a pointer-to-object type
*((int*)vp) = 3; // Must cast back to `int*' before dereferencing
cout << "i = " << i << ", *((int*)vp) = " <<
*((int*)vp) << endl; // Must cast back to `int*' before dereferencing
char c = 'A';
vp = &c; // no cast needed here
cout << "c = '" << c << "', *((char*)vp) = '" << *((char*)vp) << '\'';
cout << endl;
// *vp = 'C'; // Compile-time error: `void*' is not a pointer-to-object type
*((char*)vp) = 'C';
cout << "c = '" << c << "', *((char*)vp) = '" << *((char*)vp) << "'";
cout << endl;
return 0;
}
/*
g++ CastFromVoidPointer.cpp -o CastFromVoidPointer
./CastFromVoidPointer
i = 99, *((int*)vp) = 99
i = 3, *((int*)vp) = 3
c = 'A', *((char*)vp) = 'A'
c = 'C', *((char*)vp) = 'C'
*/