| Main |< C/C++ Pointers Part 1 | C/C++ Pointers Part 3 >| Site Index | Download |


 

 

 

 

 

C LAB WORKSHEET 11a

C & C++ Pointers  Part 2: Pointers, Array and Functions

 

 

 

 

 

  1. Relation between pointers and array.

  2. Pointers and functions.

  3. Tutorial references that should be used together with this worksheet are C & C++ pointers part 1 and C & C++ pointers part 2.

 

 

 

 

 

 

 

 

 

 

 

  1. Now let us see what operations we can do with variables that store memory addresses. First, let us have a little lesson in counting memory addresses by 1 in hex. Counting is done from 0 to 9, as we do normally. After 9, we count up to A, B, C, D, E, F and then 10 (one zero). Here, counting in memory addresses is done as a sample starting at FFDE. Adding 1 to FFDE gives us FFDF and adding 1 to that gives us FFE0 and so on.

 

... 00FFDE 00FFDF 00FFE0 00FFE1 00FFE2 00FFE3 00FFE4 00FFE5 00FFE6 00FFE7 00FFE8 00FFE9 00FFEA 00FFEB 00FFEC 00FFED 00FFEF 00FFF0 00FFF1 ...

 

Run the following program, show the output and answer the questions.

 

#include <stdio.h>

 

void main(void)

{

      char a, *pa;      // Statement 1

      pa = &a;           // Statement 2

      printf("pa = &a --> pa = %p \n", pa);

      pa = pa + 1;      // Statement 3

      printf("pa = pa + 1 --> pa = %p \n", pa);

      pa = pa + 3;      // Statement 4

      printf("pa = pa + 3 --> pa = %p \n", pa);

      pa = pa - 1;      // Statement 5

      printf("pa = pa - 1 --> pa = %p \n", pa);

}

  1. Can we add an integer to a variable such as pa that stores addresses?

  2. Can we subtract integers from a variable such as pa that store addresses?

  3. Can we multiply integers to a variable such as pa that stores addresses as shown below? What error do you get?

pa = pa * 3;

  1. What was the first address stored in pa in Statement 3?

  2. After 1 was added to pa in Statement 3, what address was stored in pa?

  3. After 3 was added to pa in Statement 4, what address was stored in pa?

  4. After 1 was subtracted from pa in Statement 5, what address was stored in pa?

  5. Now change only Statement 1 to the following statement:

int a, *pa;

  1. Rerun the program and answer the same questions, namely:

  1. What was the first address stored in pa in Statement 3?

  2. After 1 was added to pa in Statement 3, what address was stored in pa?

  3. After 3 was added to pa in Statement 4, what address was stored in pa?

  4. After 1 was subtracted from pa in Statement 5, what address was stored in pa?

  1. Adding 1 to a variable that holds character addresses adds what number to the address?

  2. Adding 1 to a variable that holds integer addresses adds what number to that address?

  3. Since the answer to question j is 1, characters are stored in memory using only 1 byte. A byte is a unit of measure of memory. How many bytes are used to store integers on your computer? Take note that the number of bytes used to store characters, integers and floats varies depending on the type of computer or platform (e.g. 32 bits, 64 bits system etc.) and/or the target platform of your program. You can use the sizeof() function to check the size of variables as shown in the following program example.

#include <stdio.h>

 

void main(void)

{

      char a = 'W';

      int b = 100;

      float c = 1.234;

      double d = 100000.34;

      printf("Size of a = %d byte(s).\n", sizeof(a));

      printf("Size of b = %d byte(s).\n", sizeof(b));

      printf("Size of c = %d byte(s).\n", sizeof(c));

      printf("Size of d = %d byte(s).\n", sizeof(d));

}

 

 

---------------------------------------------------

 

  1. Yes, we can.

  2. Yes, we can.

  3. No we can't. The following error generated.

"error C2296: '*' : illegal, left operand has type 'char *'"

  1. The address is 0013FF63.

  2. The address is 0013FF64 (0013FF63 + 1).

  3. The address is 0013FF67 (0013FF64 + 3).

  4. The address is 0013FF66 (0013FF67 - 1).

  5. (i) The address is 0013FF60.

(ii) The address is 0013FF64 (0013FF60 + 4).

(iii) The address is 0013FF70 (0013FF64 + C where C = 12 in decimal). In this case 4 x 3 = 12 in decimal).

(iv) The address is 0013FF6C (0013FF70 - 4).

  1. 1.

  2. 4.

  3. A character will take 4 bytes.

 

C/C++ pointers Windows console program output sample

   
  1. The compiler knows that if we were to add 1 to a variable that holds addresses to integers, it will actually add 4 because the next integer will be four bytes away. Now find out how many bytes are used to store floating point numbers by observing the number added when 1 is added to variable that holds the addresses of floats. Change here only the keyword float in Statement 1.

 

#include <stdio.h>

 

void main(void)

{

      float a, *pa;     // Statement 1

      pa = &a;          // Statement 2

      printf("pa = &a --> pa = %p \n", pa);

      pa = pa + 1;      // Statement 3

      printf("pa = pa + 1 --> pa = %p \n", pa);

      pa = pa + 3;      // Statement 4

      printf("pa = pa + 3 --> pa = %p \n", pa);

      pa = pa - 1;      // Statement 5

      printf("pa = pa - 1 --> pa = %p \n", pa);

}

 

    1. What was the first address that was stored in pa in Statement 2?

    2. After 1 was added to pa in Statement 3, what address was stored in pa?

    3. After 3 was added to pa in Statement 4, what address was stored in pa?

    4. After 1 was subtracted from pa in Statement 5, what address was stored in pa?

    5. How many bytes are used to store floats on your computer?

    6. Adding 5 adds how much to a variable that holds addresses for a character?

    7. Adding 5 adds how much to a variable that holds addresses for an integer?

    8. Adding 5 adds how much to a variable that holds addresses for a float?

    9. Adding 5 adds how much to a variable that holds addresses for a short int?

    10. Adding 5 adds how much to a variable that holds addresses for a long int?

    11. What about adding 5 to unsigned int?

  1. The address is 0013FF60.

  2. The address is 0013FF64 (0013FF60 + 4).

  3. The address is 0013FF70 (0013FF64 + C).

  4. The address is 0013FF6C (0013FF70 - 4).

  5. 4 bytes.

  6. 5 bytes (5 x 1 bytes).

  7. 20 bytes (5 x 4 bytes).

  8. 20 bytes (5 x 4 bytes).

  9. 10 bytes (5 x 2 bytes).

  10. 20 bytes (5 x 4 bytes).

  11. 20 bytes (5 x 4 bytes).

   
  1. Pointer and structure data type. Build, run and show the output. Then answer the questions.

 

#include <stdio.h>

 

// structure data type, you will learn this in another worksheet...

struct room

{

      float width;

      float length;

};

 

void main(void)

{

      struct room dining = {10.5f, 12.7f}, *d;

      d = &dining;

      printf("The width = %.2f The length = %.2f \n", dining.width, dining.length);

      printf("Variable pointer, d pointed to %p\n", d);

      d = d + 2;

      printf("d = d + 2, then variable pointer, d pointed to %p\n", d);

}

  1. What is the name of the pointer variable?

  2. This pointer holds addresses of what data type?

  3. Variables of this data type take how many bytes to store? How can you tell by the definition of the structure?

  4. What is the initial value of d, the pointer?

  5. What is the value of d after 2 was added to it?

  6. Do the answers in c, d and e agree? Please explain?

  1. The name is d.

  2. A structure data type that contains 2 float type elements.

  3. It will take 8 bytes (2 x 4 bytes of floats).

  4. Initial value is 0013FF5C.

  5. The value is 0013FF6C (0013FF5C + 10 where 10 in hex = 16 in decimal). The 16 comes from 2 x 8 bytes of struct room.

  6. Yes they agree. In c the struct room data type will take 8 bytes to store 2 floats of 4 bytes each. Then we add 2 to the pointer of struct room data type. In this case we need to add another 2 x 8 = 16 bytes to the original address. So 0013FF5C + 10 = 0013FF6C. 10 is in hex that equal to 16 in decimal.

   
  1. Next, let turn our attention to the addresses of array elements. Show the output and answer the questions.

 

#include <stdio.h>

 

void main(void)

{

      char a[4] = "Cup";

      printf("a = %p\n&a[0] = %p\n&a[1] = %p\n&a[2] = %p\n", a, &a[0], &a[1], &a[2]);

}

  1. Does a print an address? Show its value in the following Figure.

C/C++ pointers, arrays and memory addresses

  1. Fill in the addresses in the Figure.

  2. Is a the address of the first slot of the array, namely, &a[0]? Is the following equal:

a == &a[0]?

  1. How many bytes is a[1] away from a[0]?

  2. Elements in an array are stored next to each other. Hence, how many bytes does it take to store each character in an array of characters?

  3. If the number of bytes needed to store one character is 1 as known previously, then adding 1 to the address of a should give you &a[1], the address of a[1]. Are these two addresses the same?

printf("a + 1 = %p\n&a[1] = %p\n", a + 1, &a[1]);

 

If they are, then the condition a + 1 == &a[1]? is true.

  1. And since that is true, this should also be true:

printf("a + 2 = %p\n&a[2] = %p\n", a + 2, &a[2]);

 

Is this also true?

Answer for a. and b.

 

  1. Yes a is the address of the first slot of the array. In this case a == &a[0].

  2. 1 byte.

  3. In this case is 3 bytes (not include the null character).

  4. Yes those addresses are same as shown in the following output.

 

  1. Yes it is true as shown in the following output.

 

   
  1. Build and run the following code. Answer the questions.

 

#include <stdio.h>

 

void main(void)

{

      char a[4] = "Cup";

      printf("a = %p\n&a = %p\n", a, &a);

}

  1. You have learnt previously that we passed addresses to the scanf()/scanf_s() function and when dealing with character strings, we could send either the name of the string or its address. Then according to the experiment, is the following true?

a == &a?

  1. In conclusion, which of the following are true?

a == &a?

a == &a[0]?

a + 1 == &a[1]?

  1. Yes based on the output as shown above.

  2. All is true as shown in the following output.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  1. Let change the data type. Build and run the following code, show the output and answer the questions.

 

#include <stdio.h>

 

void main(void)

{

      int a[4];

      printf("a = %p\n&a[0] = %p\n&a[1] = %p\n&a[2] = %p\n", a, &a[0], &a[1], &a[2]);

      // notice the difference between value/data and address

      printf("\n&a[2] - &a[1] = %d, &a[1] - &a[0] = %d, &a[0] - a = %d\n", &a[2] - &a[1], &a[1] - &a[0], &a[0] - a);

}

  1. Which of the following are still true?

a == &a?

a == &a[0]?

a + 1 == &a[1]?

  1. How many bytes are used to store a float on your computer? Does this agree with previous result from experiment # 6

  2. Change the int to float in this experiment. Run it. Which of the following are still true?

a == &a?

a == &a[0]?

a + 1 == &a[1]?

  1. How many bytes are used to store a float on your computer? Does this agree with previous results from experiment # 6?

  2. Can you tell if the following statement is also true without running it? Write down your answer and then try it.

a + 1 == &a[0] + 1

  1. All still true.

 

  1. 4 bytes. Yes it agrees with the previous result.

  2. All still true.

 

  1. 4 bytes. Yes it agrees with the previous result.

  2. Yes the statement is true.

 

   
  1. For the following experiment, the data type used will not affect our conclusions. Here, we see that arrays and pointers are similar. Then we see if there is any difference between them. Build, run, show the output and answer the questions.

 

#include <stdio.h>

 

void main(void)

{

      char a[4] = "Cup";      // Statement 1

      printf("a = %p\na+1 = %p\n&a = %p\n&a[0] = %p\n&a[0] + 1 = %p\n&a[1] = %p\n", a, a+1, &a, &a[0], &a[0] + 1, &a[1]);

}

  1. a[ ] is an array, so a can store addresses. We can also change the array variable into a pointer variable. Replace Statement 1 with the following two statements.

int *a, b;

a = &b;      // assign address of variable b to variable pointer a

 

Is there any difference in the printouts?

  1. Between the two printouts, which of the following conditions are true? Complete the table.

C/C++ pointers and arrays

Yes there is a different. However both printouts are consistent in term of multiplier. In the first printout it is multiplier 1 that is for char and the second printout is multiplier 4 that is for int.

   
  1. We saw in the table above one difference between declaring a variable as a pointer and declaring a variable as an array. Here is one more experiment.

 

#include <stdio.h>

 

void main(void)

{

      float a[4], *b, c;

      b = &c;     // Statement 1

      printf("b = %p\n", b); 

}

  1. Did Statement 1 execute or did it give an error?

  2. Change Statement 1 to the following:

a = &c;

 

Try running it. Did it give an error? What was that error?

As a conclusion, both a and b store addresses, that is they are both pointers. However, the address stored in b (a pointer) can be changed, it is a pointer variable. The address of a (an array) cannot be changed, it is a pointer constant.

Statement 1 executed without error.

  1. Yes there was error as shown below.

"error C2106: '=' : left operand must be l-value"

   
  1. Pointers and function. Build, run, show the output and answer the questions.

 

#include <stdio.h>

 

// function prototype

// this function receive an array

void FlatOut(int x[ ]);  // Statement 1

 

void main(void)

{

      int a[5] = {1, 2};      // Statement 2

      // sending a pointer to the first address or

      // the address of the first array element...

      FlatOut(a);             // Statement 3

      printf("a[0] = %d, a[1] = %d\n", a[0], a[1]);

}

 

// the function definition

void FlatOut(int x[ ])     // Statement 4

{

      // assign some value to array's element...

      x[0] = 11;

      x[1] = 12;

}

  1. Did the FlatOut() function receive the address of a[ ] or copies of its values?

  2. Since it received its address, did FlatOut() change copies of array a[ ] or did it change only the locations where the array elements were stored? It changed the original locations where the array was stored because the final values of the array that were printed in main() were 11 and 12.

  3. Change Statement 1 to the following:

void FlatOut(int *x);

 

And change Statement 4 to the following:

 

void FlatOut(int *x)

 

Run the program. Is there any difference in its execution?

  1. Change Statement 3 to the following:

FlatOut(&a);

 

Is there any difference in the program’s execution?

  1. Change Statement 2 to the following:

int *a;

 

Is there any difference in the program’s execution?

 

 

 

-------------------------------------------------------------

  1. FlatOut() function receives the address of s[ ].

  2. It change the locations where the array elements were stored.

No there is no different from the previous result.

No different however there are warnings during the compilation as shown below.

 

"warning C4047: 'function' : 'int *' differs in levels of indirection from 'int (*__w64 )[5]'"

"warning C4024: 'FlatOut' : different types for formal and actual parameter 1"

  1. There are warnings during the compile time and the program cannot be executed.

"warning C4047: 'function' : 'int *' differs in levels of indirection from 'int **__w64 '"

"warning C4024: 'FlatOut' : different types for formal and actual parameter 1"

   

More Pointers Questions and Activities

 

For the following questions, use the declaration of variables shown below. You can try building a simple program using the given specification in order to answer the questions.

int i, j[5] = {4, 5, 6, 7, 8}, *ptr1 = &j[0], *ptr3;

float x[5] = {4.0, 5.0, 6.0, 7.0, 8.0}, *ptr2;

  1. For each statement below, specify which are valid and which aren’t.

 

a.    ptr1 = ptr1 + 3;

b.    j = j + 1;

c.    ptr1 = j + 1;

d.    ptr2 = ptr1;

e.    ptr1 = j[1];

f.    ptr1 = 2;

g.    i = ptr1;

h.    ptr3 = ptr1;

i.    i = j[2];

j.    ptr2 = x;

k.    ptr1 = ptr1[2];

l.    x = &ptr2[2];

m.    j = ptr1 + 3;

n.    ptr1 = &j[1];

 

  1. Valid.

  2. Valid.

  3. Valid.

  4. Not valid. Incompatible type. ptr2 is a pointer to a float but ptr1 is a pointer to an integer.

  5. Not valid. Try ptr1 = &j[1];

  6. Not valid. Assigning a constant to a pointer variable.

  7. Not valid. Assigning an address to a normal variable.

  8. Valid.

  9. Valid.

  10. Valid.

  11. Not valid. Try ptr1 = &ptr1[2];

  12. Not valid. Left operand must be left-value.

  13. Not valid. Left operand must be left-value.

  14. Valid.

   
  1. Evaluate the address of each expression. The j[ ] array begins at A008 and the x[ ] array begins at 9008.

 

a.    &j[0]

b.    j

c.    j – 2

d.    j + 4

e.    &x[4]

f.    x + 3

g.    x – 3

h.    &x[2] + 3

  1. A008.

  2. A008.

  3. A006.

  4. A00C.

  5. 900C.

  6. 900B.

  7. 9005.

  8. 900D.

 

 

 

 

 

 

 

www.tenouk.com

 

| Main |< C/C++ Pointers Part 1 | C/C++ Pointers Part 3 >| Site Index | Download |


The C & C++ Pointers: Part 1 | Part 2 | Part 3