CS 202 - Notes 2018-09-24
A digression about pointers
in the quiz, we observed that this code was invalid (in that it would crash more often than not)
int * x;
*x = 5;
This is because creating a pointer to an integer (or anything else for that matter) doesn't create the storage space as well. The only thing it does is set aside a spot in memory for an address.
In C, our variables are initialized for us, so x
will be some random value, which may or may not be a location we can write to (but it certainly is not a reliable location).
We also looked at strtol()
, which has this type declaration
long int strtol(const char *nptr, char **endptr, int base);
There was some confusion about that double pointer. The secret here is to think of it as passing in the address of a char *
so that it can be updated. This is a common idiom in C to get us around the single return value feature of functions. By passing in an address, the function can update a couple of other values as it goes.
In this case, strtol
will start at nptr
(the start of the input string), and walk down the string until it encounters a character that it can't interpret as a digit. At which point it will write the address of where it stopped into *endptr
(updating our char *
for us) before returning the value it managed to parse up to that point.
So, for example, we might use it like this:
char * cutoff;
long int value = strtol(argv[1], &cutoff, 10);
if (*cutoff != '\0'){
// bail out, there was extra garbage on the end of the string
}
Converting between bases
We have been separating the notion of value from representation. The value "twenty six", can be represented in different bases: 110102, 328, 2610, or 1A16
We can convert a number in any base b to decimal using this equation:
d3d2d1d0 = d3 * b3 + d2 * b2 + d1 * b1 + d0 * b0
Example: 110112 = 1 * 16 + 1 * 8 + 0 * 4 + 1 * 2 + 1 * 1 = 16 + 8 + 2 + 1 = 27
Example: 2A16 = 2 * 16 + 10 * 1 = 42
To convert from decimal to another base, we start by rewriting this equation slightly, progressively factoring out the bs.
((d3 * b + d2) * b + d1) * b + d0
Now consider some value V. We want to to know what d3, d2, d1, and d0.
V = ((d3 * b + d2) * b + d1) * b + d0
If we divide V by b, we get
V/b = ((d3 * b + d2) * b + d1) R d0
Now, we take the quotient and divide that by b
((d3 * b + d2) * b + d1) / b = (d3 * b + d2) R d1
And again,
(d3 * b + d2) / b = d3 R d2
And again,
d3/ b = 0 R d3
Notice that the digits we were interested in have fallen out as the remainders of all of the division.
So, we have a process to take a decimal value and convert it to another base.
- Divide the number by the base to get a quotient and a remainder
- If the quotient is not 0, set the number equal to the quotient and repeat the previous step
- Read off the remainders in reverse order to get the digits of the number in the new base