You are on page 1of 4

Lesson 18: Pointers and Stacks in C - C Tutorial Today's lesson goes more into details about pointers and

their usage as function's arguments. Additional tutorial about stacks in C and C++ is provided. Be sure to read this lesson carefully in order to understand it, since pointers are most important part of C programming language.

Transferring Arguments Address into a Function (call by reference) Write your own function that changes polar coordinates into Cartesian coordinates, and show how this function is called upon from main program.

#include <math.h>void cart(float r, float fi, float *x, float *y) { *x = r*cos( fi); // x address:1244956,value:1245052 //*x address:1245052,va lue:1.755165 *y = r*sin(fi); // y address:1244960,value:1245048 //*y address:1245048,value:0.958851} Main program slice: float x, y; // x address:1245052,value:? // y a ddress:1245048,value:?float fi = 0.5, r = 2; //fi address:1245044,value:0.5 // r address:1245040,value:2cart(r, fi, &x, &y);printf("x=%f y =%f",x,y); // x address:1245052, value:1.755165 // y address:1245048, value:0.958851

Question: What would happen if the function looked like this?

void cart(float r, float fi, float *x, float *y) { ); *y = r * cos(fi);} Important:

x = 10000; *x = r * sin(fi

Function is able to return single value through its return order. In order to return more values (in this case x & y), we can return them through arguments (Call by Reference).

Example: Write your own function that returns numerator and denominator of a fraction. This fraction is a sum of two fractions, whose two numerators and two denominators are given by user. Function also shortens the fraction if possible, before returning values. Augends numerators and denominators are integers. (Fraction example: 5/9, Numerator: 5, Denominator: 9)

void addFractions(int nrator1,int denom1, int nrator2,int denom2, int *nratorSum,int *denomSum) { int min, i; *nratorSum = nra tor1*denom2+denom1*nrator2; *denomSum = denom1*denom2; min=(*nratorSum<*deno mSum) ? *nratorSum : *denomSum; //testing if numerator and denominator //are multiples: if((*nratorSum % min == 0)&&(*denomSum % min==0)){ *nratorSum /= min; *denomSum /= min; } else { //tests if numerator and denominator are //dividable with same number i = min / 2; while ( i >= 2) { if ((*nratorSum%i == 0)&&(*denomSum%i == 0)) *nratorSum /= i; *denomSum /= i; --i; } }} Main programs slice (calls function addFractions): int nrator1, denom1, nrator2, denom2,int nratorSum, denomSum;...addFractions(nra tor1, denom1, nrator2, denom2, &nratorSum, &denomSum);

Function that finds biggest element in real numbers array Why is flows length length transferred as functions argument? float max(int length, float *p) {// OR: float max(int length, float p[]) { flo at res; int i; res = p[0]; for (i = 1; i < length; i++) if (p[i] > res) res = p[i]; return res;} Same problem - solved using pointers arithmetic: float max(int length, float *p) {float res;int i; 1; i < length; i++, p++) if (*p > res) res = *p; res = *p; p++; for (i = return res;}

Important: Pointer p stores address of the first array element. However, if we shift pointer p inside the function, address of the first arrays element wont be changed, neither will influent our main program (that calls the function).

Example: Exams results are transferred into a function in a way of array composed of integers (integers represent grades). This array (flow), is consisted of grades 1, 2, 3, 4 and 5. Number of arrays elements is nrGrades. Write your own function that returns most common grade.

int commonGrade(int *flow, int nrGrades) { int grade[5] = {0}, commonGrade = 0, i; for(i = 0; i < nrGrades; i++){ grade[flow[i] -1]++;} for(i = 1; i < 5; i++){ if(grade[i] > grade[commonGrade]) { commonGrade = i; } } return commonGrade + 1;}

Example:

Write your own function that shifts array p (given, integer type) for a number of places. Array p is consisted of N number of elements, and will be shifted left for negative value, or shifted right for positive value (adjustment < N). Empty places are filled with zeroes. Example of shifting: shift = 2 and array[10 40 50 60 12]: Before shifting: [10 40 50 60 12] Shifted array: [ 0 0 10 40 50]

Solution: void shiftArray(int *p, int N, int shift) { int i; // if shifting right if ( shift > 0 && shift < N) { for (i = N - 1 - shift; i >= 0; i --) p[i + shift] = p[i]; for (i = shift - 1; i >= 0; i --) p[i] = 0; } // if shifting left else if (shift < 0 && -shift < N) { shift = -shift; for (i = 0; i <= N - 1 - shift; i++) p[i] = p[i + shift]; for (i = N - shift; i < N; i++) p[i] = 0; }}

Stack Data Storage with Function call Every new element is stored on top of the stack. However, compilers often tend to assign lower address to stacks top, then to stacks bottom. This results data being stored downwards (from bottom of the stack to lower memory addresses).

Following data is stored to a stack (from higher addresses to lower ones): - functions arguments (highest address is assigned to ultimately-right placed argument) - returning address - local variables (highest address is assigned to first declared variable)

Important: While transferring data to a stack, frames of the stack will be ignored in this tutorial (processor registers). However, some compilers also tend to store these to a stack.

For how many bytes does the stack maximally increase, while executing this block: ... ... y = f1(10); ...

if the following functions are defined: long f2(float a, float b) { return a + b;}int f1(char x) { int i = 4, y; y = x + 1; return i * f2(x, y);} f1 call: STACKS TOP f2 call:

(lower addresses) returning address 2 10 (float) ^ 11 (float) / \1 1 (int) 11 (int) / \4 (int) 4 (int) / __ \returning address 1 returning add ress 1 10 (char) 10 (char) STACKS BOTTOM (higher addresses)

Returning address is data type long. By calling function f2, stack has increased to its maximal size: sizeof(char) + sizeof(returning address 1) + 2 * sizeof(int) + 2 * sizeof(float) + sizeof(returning address 2) --------------= 25 by te

You might also like