#include <iostream>
using std::cout;
using std::endl;
int main()
{
int i[10];
double d[10];
int* ip = i;
double* dp = d;
cout << "sizeof(int) = " << sizeof(int) << endl;
cout << "ip = " << (long)ip << endl;
ip++;
cout << "ip = " << (long)ip << endl;
ip--;
cout << "ip = " << (long)ip << endl;
cout << "ip+2 = " << (long)(ip+2) << endl;
cout << endl;
cout << "sizeof(double) = " << sizeof(double) << endl;
cout << "dp = " << (long)dp << endl;
dp++;
cout << "dp = " << (long)dp << endl;
dp--;
cout << "dp = " << (long)dp << endl;
cout << "dp-1 = " << (long)(dp-1) << endl;
return 0;
}
/*
g++ PointerIncrement1.cpp -o PointerIncrement1
./PointerIncrement1
sizeof(int) = 4
ip = 140731920911760
ip = 140731920911764
ip = 140731920911760
ip+2 = 140731920911768
sizeof(double) = 8
dp = 140731920911808
dp = 140731920911816
dp = 140731920911808
dp-1 = 140731920911800
*/
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
#include <iostream>
using std::cout;
using std::endl;
typedef struct
{ // word size = 8 bytes alignment?
char c; // sizeof(char) = 1 byte (next is 2B, so 1B padding), 2B total
short s; // 2 bytes (next 4B, currently 4B total, no padding here), 4B
int i; // 4 bytes (next 8B, 8B so far, no padding here), 8B
long l; // 8 bytes (16B total, multiple of 8, no padding here), 16B
float f; // 4 bytes (20B so far, 4B padding), 24B total (multiple of 8)
double d; // 8 bytes (32B total, multiple of 8 and 16, no padding), 32B
long double ld; // 16 bytes (forces 16B alignment), 48B
} Primitives; // 48 bytes in total (multiple of 16, largest member)
int main()
{
Primitives p[10];
Primitives* pp = p;
cout << "word size: sizeof(size_t) = " << sizeof(size_t) << endl;
cout << "sizeof(Primitives) = " << sizeof(Primitives) << endl;
cout << "p = " << (long)p << endl;
cout << "pp = " << (long)pp << endl;
// p++; // compile error: not lvalue
pp++;
cout << "After increment:" << endl;
cout << "p = " << (long)p << endl;
cout << "pp = " << (long)pp << endl;
// p--; // compile error: not lvalue
pp--;
cout << "After decrement:" << endl;
cout << "p = " << (long)p << endl;
cout << "pp = " << (long)pp << endl;
cout << "p+2 = " << (long)(p+2) << endl;
cout << "pp+2 = " << (long)(pp+2) << endl;
cout << "p-1 = " << (long)(p-1) << endl;
cout << "pp-1 = " << (long)(pp-1) << endl;
return 0;
}
/*
g++ PointerIncrement2.cpp -o PointerIncrement2
./PointerIncrement2
word size: sizeof(size_t) = 8
sizeof(Primitives) = 48
p = 140737044809504
pp = 140737044809504
After increment:
p = 140737044809504
pp = 140737044809552
After decrement:
p = 140737044809504
pp = 140737044809504
p+2 = 140737044809600
pp+2 = 140737044809600
p-1 = 140737044809456
pp-1 = 140737044809456
*/
size_t is defined as long unsigned int in stddef.h, on disk /usr/lib/gcc/x86_64-linux-gnu/9/include/stddef.h (see also stdint.h, on disk /usr/include/stdint.h).
See How_to_detect_machine_word_size on StackOverflow and Data_structure_alignment on Wikipedia.
Check these structs:
typedef struct
{ // word size = 8 bytes alignment?
char c; // sizeof(char) = 1 byte
} Primitives; // 1 byte in total (multiple of 1, size of largest member)
typedef struct
{ // word size = 8 bytes alignment?
short s; // sizeof(short) = 2 bytes
} Primitives; // 2 bytes in total (multiple of 2)
typedef struct
{ // word size = 8 bytes alignment?
char c; // sizeof(char) = 1 byte (next 2B, 1B padding)
short s; // sizeof(short) = 2 bytes
} Primitives; // 4 bytes in total (multiple of 2, largest member)
typedef struct
{ // word size = 8 bytes alignment?
char c; // sizeof(char) = 1 byte (next 16B, 15B padding)
long double ld; // sizeof(long double) = 16 bytes
} Primitives; // 32 bytes in total (multiple of 16, largest member)
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
Exercise 3-23. Modify PointerIncrement2.cpp (see ch3-PointerIncrement) so it uses a union instead of a struct.
#include <iostream>
using std::cout;
using std::endl;
typedef union
{
char c; // sizeof(char) = 1 byte
short s; // 2 bytes
int i; // 4 bytes
long l; // 8 bytes
float f; // 4 bytes
double d; // 8 bytes
long double ld; // 16 bytes
} Primitives; // 16 bytes (largest member)
int main()
{
Primitives p[10];
Primitives* pp = p;
cout << "sizeof(Primitives) = " << sizeof(Primitives) << endl;
cout << "p = " << (long)p << endl;
cout << "pp = " << (long)pp << endl;
// p++; // compile error: not lvalue
pp++;
cout << "After increment:" << endl;
cout << "p = " << (long)p << endl;
cout << "pp = " << (long)pp << endl;
// p--; // compile error: not lvalue
pp--;
cout << "After decrement:" << endl;
cout << "p = " << (long)p << endl;
cout << "pp = " << (long)pp << endl;
cout << "p+2 = " << (long)(p+2) << endl;
cout << "pp+2 = " << (long)(pp+2) << endl;
cout << "p-1 = " << (long)(p-1) << endl;
cout << "pp-1 = " << (long)(pp-1) << endl;
return 0;
}
/*
g++ PointerIncrementUnion.cpp -o PointerIncrementUnion
./PointerIncrementUnion
sizeof(Primitives) = 16
p = 140723180902672
pp = 140723180902672
After increment:
p = 140723180902672
pp = 140723180902688
After decrement:
p = 140723180902672
pp = 140723180902672
p+2 = 140723180902704
pp+2 = 140723180902704
p-1 = 140723180902656
pp-1 = 140723180902656
*/
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
#include <iostream>
using std::cout;
using std::endl;
#define P(EX) cout << #EX << ": " << EX << endl; // print
int main()
{
int a[10];
for(int i = 0; i < 10; i++)
{a[i] = i+10;} // index values + 10
int* ip1 = a;
P(*ip1) // 10 (first element)
P(*++ip1) // 11 (ip1 points now to second element)
P(ip1 - a) // no of elements between the two pointers (1)
P(a - ip1) // no of elements between the two pointers (-1)
P(*(ip1 + 5)) // 16 (seventh element)
int* ip2 = ip1 + 5;
P(*ip2) // 16
P(*(ip2 - 4)) // 12 (third element)
P(*--ip2) // 15 (ip2 points now to sixth element)
P(ip2 - ip1) // no of elements between the two pointers (4)
P(ip1 - ip2) // no of elements between the two pointers (-4)
return 0;
}
/*
g++ PointerArithmetic.cpp -o PointerArithmetic
./PointerArithmetic
*ip1: 10
*++ip1: 11
ip1 - a: 1
a - ip1: -1
*(ip1 + 5): 16
*ip2: 16
*(ip2 - 4): 12
*--ip2: 15
ip2 - ip1: 4
ip1 - ip2: -4
*/
cout << "*ip1" << ": " << *ip1 << endl;;
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
*****************************************************************************************
Exercise 3-24. Modify PointerArithmetic.cpp to work with long and long double.
#include <iostream>
using std::cout;
using std::endl;
#define P(EX) cout << #EX << ": " << EX << endl; // print
int main()
{
long a[10];
long double b[10];
for(int i = 0; i < 10; i++)
{
a[i] = i+10;
b[i] = i+20;
}
long* lp1 = a;
P(*lp1) // 10 (first element)
P(*++lp1) // 11 (lp1 points now to second element)
P(lp1 - a) // no of elements between the two pointers (1)
P(a - lp1) // no of elements between the two pointers (-1)
P(*(lp1 + 5)) // 16 (seventh element)
long* lp2 = lp1 + 5;
P(*lp2) // 16
P(*(lp2 - 4)) // 12 (third element)
P(*--lp2) // 15 (lp2 points now to sixth element)
P(lp2 - lp1) // no of elements between the two pointers (4)
P(lp1 - lp2) // no of elements between the two pointers (-4)
cout << endl;
// long double* ldp1 = a; // compile error: cannot convert long to long double
long double* ldp1 = b;
P(*ldp1) // 20 (first element)
P(*++ldp1) // 21 (ldp1 points now to second element)
// P(ldp1 - a) // compile error: cannot compare long and long double pointers
P(ldp1 - b) // no of elements between the two pointers (1)
P(b - ldp1) // no of elements between the two pointers (-1)
P(*(ldp1 + 5)) // 26 (seventh element)
long double* ldp2 = ldp1 + 5;
P(*ldp2) // 26
P(*(ldp2 - 4)) // 22 (third element)
P(*--ldp2) // 25 (ldp2 points now to sixth element)
P(ldp2 - ldp1) // no of elements between the two pointers (4)
P(ldp1 - ldp2) // no of elements between the two pointers (-4)
return 0;
}
/*
g++ PointerArithmeticLongDouble.cpp -o PointerArithmeticLongDouble
./PointerArithmeticLongDouble
*lp1: 10
*++lp1: 11
lp1 - a: 1
a - lp1: -1
*(lp1 + 5): 16
*lp2: 16
*(lp2 - 4): 12
*--lp2: 15
lp2 - lp1: 4
lp1 - lp2: -4
*ldp1: 20
*++ldp1: 21
ldp1 - b: 1
b - ldp1: -1
*(ldp1 + 5): 26
*ldp2: 26
*(ldp2 - 4): 22
*--ldp2: 25
ldp2 - ldp1: 4
ldp1 - ldp2: -4
*/