// datatype to represent a fraction as a numerator and denominator struct Fraction { int numerator; int denominator; }; const double SomeGlobal = 12; |
// get two ints from the user // and store in integers referenced by the pointer parameters // (shows use of pointers to achieve pass-by-ref effect) void getVals(int* ptr1, int* ptr2); // display various memory addresses and values associated with the parameters void displayStruct(Fraction* fptr); void displayInt(int* iptr, int* jptr); |
int main() { cout << endl << "===Inside main===" << endl; // declare a mix of local variables: ints, pointers to ints, structs, pointers to structs int a = 10; int b = 20; Fraction F = { 1, 2 }; Fraction G = { 5, 7 }; int* ptrForInts = &a; // points at a Fraction* ptrForFracs = &F; // points at F // show addresses and contents of local variables and global constant cout << "Addresses (in hexadecimal), sizes (bytes), and values of locals are:" << endl; cout << " a: " << (&a) << ", size: " << sizeof(int) << ", value: " << a << endl; cout << " b: " << (&b) << ", size: " << sizeof(int) << ", value: " << b << endl; cout << " F: " << (&F) << ", size: " << sizeof(Fraction) << ", numer: " << F.numerator << ", denom: " << F.denominator << endl; cout << " G: " << (&G) << ", size: " << sizeof(double) << ", numer: " << G.numerator << ", denom: " << G.denominator << endl; cout << "And for the pointer variables:" << endl; cout << " ptrForInts: " << (&ptrForInts) << ", size: " << sizeof(int*) << ", value: " << ptrForInts << " (should match a's addr)" << endl; cout << " ptrForFracs: " << (&ptrForFracs) << ", size: " << sizeof(Fraction*) << ", value: " << ptrForFracs << " (should match F's addr)" << endl; cout << "And for global constant SomeGlobal:" << endl; cout << "addr: " << (&SomeGlobal) << ", size: " << sizeof(double) << ", value: " << SomeGlobal << endl; } |
// use displayInt on the pointer to a and the address of b displayInt(ptrForInts, &b); // similarly with displayStruct displayStruct(ptrForFracs); displayStruct(&G); |
// use getVals to alter the values of a (through the pointer) and b, show the new contents getVals(ptrForInts, &b); cout << "===Back in main===" << endl; cout << "Revised a: " << a << ", revised b: " << b << endl; // similarly for the fields of F (numerator through the pointer) getVals(&(ptrForFracs->numerator), &(F.denominator)); cout << "===Back in main===" << endl; cout << "Revised fraction numerator: " << F.numerator; cout << ", denominator: " << F.denominator << endl << endl; } |
void getVals(int* ptr1, int* ptr2) { cout << endl << "===Inside getVals===" << endl; cout << "Enter two integers: "; cin >> (*ptr1); cin >> (*ptr2); } |
void displayInt(int* iptr, int* jptr) { cout << endl << "===Inside displayInt===" << endl; // show addresses and contents of parameters and the ints they 'point at' cout << "Addr stored in iptr param: " << iptr << ", value stored there: " << (*iptr) << endl; cout << "Addr stored in jptr param: " << jptr << ", value stored there: " << (*jptr) << endl; } |
void displayStruct(Fraction* fptr) { cout << endl << "===Inside displayStruct===" << endl; cout << "Addr stored in fptr param: " << fptr << endl; cout << "Addr of numerator field is: " << (&(fptr->numerator)); // example accessing a field (numerator) using -> notation cout << ", value stored there: " << fptr->numerator << endl; cout << "Addr of denominator field is: " << (&(fptr->denominator)); // example accessing a field (denominator) using *. notation cout << ", value stored there: " << (*fptr).denominator << endl; } |
===Inside main=== Addresses (in hexadecimal), sizes (bytes), and values of locals are: a: 0x7ffe3a4e0d1c, size: 4, value: 10 b: 0x7ffe3a4e0d18, size: 4, value: 20 F: 0x7ffe3a4e0d10, size: 8, numer: 1, denom: 2 G: 0x7ffe3a4e0d08, size: 8, numer: 5, denom: 7 And for the pointer variables: ptrForInts: 0x7ffe3a4e0d00, size: 8, value: 0x7ffe3a4e0d1c (should match a's addr) ptrForFracs: 0x7ffe3a4e0cf8, size: 8, value: 0x7ffe3a4e0d10 (should match F's addr) And for global constant SomeGlobal: addr: 0x55dcb80a94b0, size: 8, value: 12 ===Inside displayInt=== Addr stored in iptr param: 0x7ffe3a4e0d1c, value stored there: 10 Addr stored in jptr param: 0x7ffe3a4e0d18, value stored there: 20 ===Inside displayStruct=== Addr stored in fptr param: 0x7ffe3a4e0d10 Addr of numerator field is: 0x7ffe3a4e0d10, value stored there: 1 Addr of denominator field is: 0x7ffe3a4e0d14, value stored there: 2 ===Inside displayStruct=== Addr stored in fptr param: 0x7ffe3a4e0d08 Addr of numerator field is: 0x7ffe3a4e0d08, value stored there: 5 Addr of denominator field is: 0x7ffe3a4e0d0c, value stored there: 7 ===Inside getVals=== Enter two integers: 100 200 ===Back in main=== Revised a: 100, revised b: 200 ===Inside getVals=== Enter two integers: 300 400 ===Back in main=== Revised fraction numerator: 300, denominator: 400 |
variable | addr (hex) | addr (decimal) | size (bytes) |
a | d1c | 2396 | 4 |
b | d18 | 2392 | 4 |
F | d10 | 2384 | 8 |
G | d08 | 2376 | 8 |
ptrForInts | d00 | 2368 | 8 |
ptrForFracs | cf8 | 2360 | 8 |
#include <iostream> #include <string> #include <ctime> #include <cstdlib> using std::cin; using std::cout; using std::cerr; using std::endl; using std::string; using std::nothrow; // structure to hold an array of numbers and its size, // using a pointer for the array since it will be dynamically allocated/deallocated struct numArray { long size; long* data; }; // maximum number of characters to skip on bad input const int LineLen = 80; |
// get a non-negative integer value from the user (using the prompt provided) long getInteger(string prompt); // attempt to allocate the array within narr, using the specified array size, // return true if successful, false otherwise bool allocate(numArray &narr, long sz); // deallocate the array component of narr and set the data and size // fields to null and 0 to indicate it is now empty void deallocate(numArray &narr); // fill the given numArray with random values in the range min..max (inclusive) void fillRand(numArray &narr, long min, long max); // print the given numArray's content void print(numArray narr); |
int main() { // initialize the random number generator srand(time(NULL)); // set up the empty table and get the desired size and value range from the user numArray dataTable; int numEntries = getInteger("How many data values would you like to store?"); int minVal = getInteger("What is the smallest allowable data value (integer)?"); int maxVal = getInteger("What is the largest allowable data value (integer)?"); // attempt to allocate the table, then fill, print, and deallocate it if successful if (allocate(dataTable, numEntries)) { cout << "Now filling the table with random data" << endl; fillRand(dataTable, minVal, maxVal); cout << "The resulting table content is:" << endl; print(dataTable); cout << "Now deleting the table" << endl; deallocate(dataTable); } } |
bool allocate(numArray &narr, long sz) { // check the size is valid and attempt the allocation if (sz > 0) { narr.data = nullptr; narr.size = 0; narr.data = new(nothrow) long[sz]; if (narr.data) { narr.size = sz; return true; } else { cerr << "Error: allocation failed for array of " << sz << " longs" << endl; } } else { cerr << "Error: allocate needs a positive number of elements (given " << sz << ")" << endl; } return false; } |
void deallocate(numArray &narr) { if (narr.data) { delete [] narr.data; narr.data = nullptr; narr.size = 0; } else { cerr << "Warning: deallocate called on unallocated array" << endl; } } |
void fillRand(numArray &narr, long min, long max) { if (narr.data == nullptr) { cerr << "Warning: fill called on unallocated array" << endl; } else if (narr.size < 1) { cerr << "Warning: fill called on array with 0 or negative size ("; cerr << narr.size << ")" << endl; } else if (min > max) { cerr << "Warning: fill called with impossible data range (values > "; cerr << min << " but < " << max << ")" << endl; } else { for (int p = 0; p < narr.size; p++) { // generate a pseudo-random value in the range min..max (inclusive) long val = min + (rand() % (1 + max - min)); // place in the next position in the array narr.data[p] = val; } } } void print(numArray narr) { if (narr.data == nullptr) { cerr << "Warning: print called on unallocated array" << endl; } else if (narr.size < 1) { cerr << "Warning: print called on array with 0 or negative size ("; cerr << narr.size << ")" << endl; } else { for (int p = 0; p < narr.size; p++) { // display the next array element cout << narr.data[p] << endl; } } } |
How many data values would you like to store? 7 What is the smallest allowable data value (integer)? 13 What is the largest allowable data value (integer)? 104 Now filling the table with random data The resulting table content is: 42 90 61 86 13 51 71 Now deleting the table |