In CPU, a switch is to describe a bit. A bit represent either 0 or 1. You switch on or off. 1 or 0. Thus, its called a switch.
Eight of these bits make up a byte. Each representation of these bits make up a representation. For example, in a byte, we can have:
00000000 (0)
00000001 (1)
00000010 (2)
00000011 (3)
…etc
So as you can see, if we were to make each representation a number, we can have up to
2^8-1 representations. where 8 is the number of bits.
Currently, the example is binary.
Hexadecimal Numbers is a more complex system than using just binary or decimal and is mainly used when dealing with computers and memory address locations.
By dividing a binary number up into groups of 4 bits, each group or set of 4 digits can now have a possible value of between “0000” (0) and “1111” ( 8+4+2+1 = 15 ) giving a total of 16 different number combinations from 0 to 15. Don’t forget that “0” is also a valid digit.
Thus, a 4 bit binary number is a hex digit. If a system has 32 bits, we can say it has 8 hex digits.
If we were to work with hex, each hex digit would have 16 representations: 0123456789abcdef
In computers, data is represented by an address. An address is a hex representation.
The address of a variable is the location in memory where the value for that variable is stored.
To get the variable’s address, you use the & operator:
1 2 3 4 5 |
#include <stdio.h> int main(int argc, const char * argv[]) { int i = 17; printf("i stores its value at %pn", &i); return 0; } |
Notice the %p token. That’s the token you can replace with a memory address. Build and run
the program. You’ll see something like:
i stores its value at 0xbffff738
its in hex which is calculated like this
1 |
0xbffff738 is b*(16^7) f*(16^6) f*(16^5)+ f*(16^4)+ f*(16^3) + 7*(16^2) + 3*(16^1) + 8*(16^0) |
Storing Addresses in pointers
Declare a new variable named addressOfI that is a pointer to an int. Assign it the address of
i.
1 2 3 4 5 6 |
int main(int argc, const char * argv[]) { int i = 17; int *addressOfI = &i; printf("i stores its value at %pn", addressOfI); printf("this function starts at %pn", main); return 0; } |
Getting the data at the address
1 2 3 4 5 6 7 |
int main(int argc, const char * argv[]) { int i = 17; int *addressOfI = &i; printf("i stores its value at %pn", addressOfI); printf("this function starts at %pn", main); printf("the int stored at addressOfI is %dn", *addressOfI); return 0; } |
Notice that the asterisk is used two different ways The first is in the declaration where you declare the variable addressOfI to be an int *. That is, it is a pointer to a place where an int can be stored.
The second is where you read the int value that is stored at the address stored in addressOfI. (Pointers are also called references. Thus, using the pointer to read data at the address is sometimes called dereferencing the pointer.)
You can also use the * operator on the left-hand side of an assignment to store data at a particular address:
1 2 3 4 5 6 7 |
int main(int argc, const char * argv[]) { int i = 17; int *addressOfI = &i; printf("i stores its value at %pn", addressOfI); *addressOfI = 89; printf("Now i is %dn", i); return 0; } |
Passing the Reference…by value
This is known as pass-by-reference. That is, you supply an address (also known as “a reference”), and the function puts the data there.
Changes would take place inside method ONLY if you do not move pointer
If you don’t move the parameter pointer, it would work.
For example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
-(void)test3:(int*)ptr { DLOG(@"%p", ptr); *ptr = 6680; //changes outside because we are passing a reference in //and having our pointer parameter point to it. } main(..) { int variable = 897; DLOG(@"%p", &variable); //here variable would be 897 [self test3:&variable]; //here variable would be 6680 } |
In detail, here’s why its pass by value of the reference:
1 2 3 4 5 6 7 8 9 10 11 12 |
-(void)test4:(int*)ptr { DLOG(@"%p", ptr); *ptr = 6680; //changes outside because we are passing a reference in //and having our pointer parameter point to it. ptr = new int; *ptr = 243; DLOG(@"%p", ptr); DLOG(@"%u", *ptr); } |
1 2 3 4 5 6 |
int variable = 897; DLOG(@"%p", &variable); [self test4:&variable]; DLOG(@"variable is: %u", variable); |
If you run it, you’ll see that the ptr inside the function points away to another fresh allocated integer. The outside did not move.
In order to really use a reference (similar to that of C++) to modify the data passed into a method, you need to use a double ptr:
Using pointer of pointer to make changes permanent from inside the method
1 2 3 4 5 6 7 |
-(void)ChangePermanently:(int**)dblPtr { **dblPtr = *new int(100); NSLog(@"**dblPtr s: %u", **dblPtr); NSLog(@"address of the integer is *dblPtr: %p", *dblPtr); NSLog(@"the address of the pointer pointing to the integer is dblPtr: %p", dblPtr); } |
1 2 3 4 5 6 7 8 9 |
int * numPtr = new int(2); NSLog(@"data pointed to by numPtr is *numPtr: %u", *numPtr); NSLog(@"address pointed to by numPtr is numPtr: %p", numPtr); [self ChangePermanently:&numPtr]; NSLog(@"data pointed to by numPtr is *numPtr: %u", *numPtr); NSLog(@"address pointed to by numPtr is numPtr: %p", numPtr); NSLog(@"the address of the pointer pointing to data numPtr is &numPtr: %p", &numPtr); |
Pass by Copy
1 2 3 4 5 |
-(void)test2:(int)passByValue { DLOG(@"%p", &passByValue); passByValue = 43; } |
As you can see, the address of our variable is different outside, than the address of the parameter variable inside test2.
1 2 3 4 5 6 7 8 9 |
void main() { DLOG(@"AppDelegate.m - applicationDidBecomeActive"); int variable = 897; DLOG(@"%p", &variable); [self test2:variable]; DLOG(@"variable is: %u", variable); } |
Basically you just copy the value in. The parameter is basically a newly created variable on the stack with a different address, but has the same value as what you pass in.