Monday, January 26, 2009

Pointers

Pointers
The source code to all code listings is available as a tarball and as a zip file.

Using Variables
Essentially, the computer's memory is made up of bytes. Each byte has a number, an address, associated with it.
The picture below represents several bytes of a computer's memory. In the picture, addresses 924 thru 940 are shown.

Try:
C Code Listing 1
1:#include
2:int main()
3:{
4: float fl=3.14;
5: printf("%.2f\n", fl);
6: return 0;
7:}
C++ Code Listing 1
1:#include
2:int main()
3:{
4: float fl=3.14;
5: std::cout <<>
2: int main()
3: {
4: float fl=3.14;
5: printf("fl's address=%u\n", (unsigned int) &fl);
6: return 0;
7: }
C++ Code Listing 2
1:#include
2: int main()
3: {
4: float fl=3.14;
5: std::cout << "fl's address=" << (unsigned int) &fl <<>
2: int main()
3: {
4: float fl=3.14;
5: unsigned int addr=(unsigned int) &fl;
6: printf("fl's address=%u\n", addr);
7: return 0;
8: }
C++ Code Listing 3
1: #include
2: int main()
3: {
4: float fl=3.14;
5: unsigned int addr=(unsigned int) &fl;
6: std::cout << "fl's address=" <<>
2: int main()
3: {
4: float fl=3.14;
5: unsigned int addr=(unsigned int) &fl;
6: printf("fl's address=%u\n", addr);
7: printf("addr's contents=%.2f\n", * (float*) addr);
8: return 0;
9: }
C++ Code Listing 4
1: #include
2: int main()
3: {
4: float fl=3.14;
5: unsigned int addr=(unsigned int) &fl;
6: std::cout << "fl's address=" << contents=" << * (float*) addr << std::endl; 8: return 0; 9: } In line (7), step 2 has been performed on a number: 2. The contents stored at that address [addr] are retrieved. In order to make line (7) work, a little ">
2: void somefunc(float fvar)
3: {
4: fvar=99.9;
5: }
6: int main()
7: {
8: float fl=3.14;
9: somefunc(fl);
10: printf("%.2f\n", fl);
11: return 0;
12: }
C++ Code Listing 5
1: #include
2: void somefunc(float fvar)
3: {
4: fvar=99.9;
5: }
6: int main()
7: {
8: float fl=3.14;
9: somefunc(fl);
10: std::cout <<>
2: void somefunc(unsigned int fptr)
3: {
4: *(float*)fptr=99.9;
5: }
6:
7: int main()
8: {
9: float fl=3.14;
10: unsigned int addr=(unsigned int) &fl;
11: somefunc(addr);
12: printf("%.2f\n", fl);
13: return 0;
14: }
C++ Code
1: #include
2: void somefunc(unsigned int fptr)
3: {
4: *(float*)fptr=99.9;
5: }
6:
7: int main()
8: {
9: float fl=3.14;
10: unsigned int addr=(unsigned int) &fl;
11: somefunc(addr);
12: std::cout << fl="3.14;" addr =" &fl;" fl="3.14;" addr =" &fl;">
2: void somefunc(unsigned int fptr)
3: {
4: *(float*)fptr=99.9;
5: }
6:
7: int main()
8: {
9: float fl=3.14;
10: unsigned int addr=(unsigned int) &fl;
11: somefunc(addr);
12: printf("%.2f\n", fl);
13: return 0;
14: }
C++ Code Listing 7
1: #include
2: void somefunc(unsigned int fptr)
3: {
4: *(float*)fptr=99.9;
5: }
6:
7: int main()
8: {
9: float fl=3.14;
10: unsigned int addr=(unsigned int) &fl;
11: somefunc(addr);
12: std::cout <<>
2: void somefunc(float* fptr)
3: {
4: *fptr=99.9;
5: }
6:
7: int main()
8: {
9: float fl=3.14;
10: float* addr = &fl;
11: somefunc(addr);
12: printf("%.2f\n", fl);
13: return 0;
14: }
C++ Code Listing 8
1: #include
2: void somefunc(float* fptr)
3: {
4: *fptr=99.9;
5: }
6:
7: int main()
8: {
9: float fl=3.14;
10: float* addr = &fl;
11: somefunc(addr);
12: std::cout << fl << std::endl;
13: return 0;
14: }
• On line (10), when we take the address of fl the address is assigned to a variable designed to hold it. No casting is required.
• When addr is passed to the function in line (11), addr is copied to fptr on line (2).
• Line (2) shows that fptr is created as a float pointer, that is a variable designed to hold the address of a floating point number. As a result, no casting is needed on line (4) where the contents at the address are retrieved.

Cigars - All your favorite cigars online at wholesale.
Premium Cigars - Premium cigars at discount prices.

Kia Dealers - Get multiple Kia price quotes from competing Kia Dealers
Used Autos - Autotropolis.com is your #1 stop for auto reviews and comparisons on new automobiles and trucks.

operator of Pointers

Two operators are provided that, when used, cause these two steps to occur separately.

operator

meaning

example

&

do only step 1 on a variable

&fl

*

do step 2 on a number(address)

*some_num


Try this code to see what prints out:

C Code Listing 2

1: #include
2: int main()
3: {
4: float fl=3.14;
5: printf("fl's address=%u\n", (unsigned int) &fl);
6: return 0;
7: }
C++ Code Listing 2
1:#include
2: int main()
3: {
4: float fl=3.14;
5: std::cout << "fl's address=" << (unsigned int) &fl <<>
2: int main()
3: {
4: float fl=3.14;
5: unsigned int addr=(unsigned int) &fl;
6: printf("fl's address=%u\n", addr);
7: return 0;
8: }

C++ Code Listing 3
1: #include
2: int main()
3: {
4: float fl=3.14;
5: unsigned int addr=(unsigned int) &fl;
6: std::cout << "fl's address=" << addr << std::endl;
7: return 0;
8: }




The above code shows that there is nothing magical about addresses. They are just simple numbers that can be stored in integer variables.

The unsigned keyword at the start of line (5) simply means that the integer will not hold negative numbers. As before, the (unsigned int) phrase has been shown in gray. It must be included for the code to compile, but is not relevant to this discussion. It will be discussed later.

Now let's test the other operator, the * operator that retrieves the contents stored at an address:

C Code Listing 4
1: #include
2: int main()
3: {
4: float fl=3.14;
5: unsigned int addr=(unsigned int) &fl;
6: printf("fl's address=%u\n", addr);
7: printf("addr's contents=%.2f\n", * (float*) addr);
8: return 0;
9: }

C++ Code Listing 4
1: #include
2: int main()
3: {
4: float fl=3.14;
5: unsigned int addr=(unsigned int) &fl;
6: std::cout << "fl's address=" << addr << std::endl;
7: std::cout << "addr's contents=" << * (float*) addr << std::endl;
8: return 0;
9: }

In line (7), step 2 has been performed on a number:
2. The contents stored at that address [addr] are retrieved.

In order to make line (7) work, a little "syntax sugar" had to be added for the program to compile. Like before, (float*) is shown in gray because it is not relevant to the current discussion. For the sake of this discussion, just read "*(float*)addr" as "*addr" (that is, ignore the stuff in gray). The code shown in gray will be discussed later.

Pointers in C and C++ - Using Variables

Essentially, the computer's memory is made up of bytes. Each byte has a number, an address, associated with it.

The picture below represents several bytes of a computer's memory. In the picture, addresses 924 thru 940 are shown.


Try:

C Code Listing 1

 1:#include 
 2:int main()
 3:{
 4:  float fl=3.14;
 5:  printf("%.2f\n", fl);
 6:  return 0;
 7:}

C++ Code Listing 1

 1:#include 
 2:int main()
 3:{
 4:  float fl=3.14;
 5:  std::cout <<>
 6:  return 0;
 7:}

At line (4) in the program above, the computer reserves memory for fl. In our examples, we'll assume that a float requires 4 bytes. Depending on the computer's architecture, a float may require 2, 4, 8 or some other number of bytes.

When fl is used in line (5), two distinct steps occur:

  1. The program finds and grabs the address reserved for fl--in this example 924.
  2. The contents stored at that address are retrieved

To generalize, whenever any variable is accessed, the above two
distinct steps occur to retrieve the contents of the variable.

The illustration that shows 3.14 in the computer's memory can be misleading.
Looking at the diagram, it appears that "3" is stored in memory location 924,
"." is stored in memory location 925, "1" in 926, and "4" in 927.
Keep in mind that the computer actually uses an algorithm to convert the
floating point number 3.14 into a set of ones and zeros. Each byte holds 8
ones or zeros. So, our 4 byte float is stored as 32 ones and zeros (8 per byte times 4 bytes).
Regardless of whether the number is 3.14, or -273.15, the number is always
stored in 4 bytes as a series of 32 ones and zeros.