Lesson 18: Pointers and Stacks in C


E-mail this post



Remember me (?)



All personal information that you provide here will be governed by the Privacy Policy of Blogger.com. More...



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 Argument’s 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,value: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 address:1245048,value:?

float fi = 0.5, r = 2; //fi address:1245044,value:0.5
// r address:1245040,value:2

cart(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) {

x = 10000;
*x = r * sin(fi);
*y = r * cos(fi);

}



Important:

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 = nrator1*denom2+denom1*nrator2;
*denomSum = denom1*denom2;

min=(*nratorSum<*denomSum) ? *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 program’s slice (calls function addFractions):

int nrator1, denom1, nrator2, denom2,
int nratorSum, denomSum;

...

addFractions(nrator1, denom1, nrator2,
denom2, &nratorSum, &denomSum);




Function that finds biggest element in real number’s array

Why is flow’s length “length” transferred as function’s argument?

float max(int length, float *p) {

// OR: float max(int length, float p[]) {

float 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 pointer’s arithmetic:

float max(int length, float *p) {

float res;
int i;


res = *p;
p++;
for (i = 1; i < length; i++, p++)
if (*p > res)
res = *p;
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 array’s element won’t be changed, neither will influent our main program (that calls the function).




Example:

Exam’s 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 array’s 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 stack’s top, then to stack’s 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):

- function’s 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: f2 call: STACK’S TOP
(lower addresses)
returning address 2
10 (float) ^
11 (float) / \
11 (int) 11 (int) / \
4 (int) 4 (int) / __ \
returning address 1 returning address 1
10 (char) 10 (char) STACK’S 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 byte















Technorati Tags:
, , , , , ,




3 Responses to “Lesson 18: Pointers and Stacks in C”

  1. Anonymous vurdlak 

    This lesson continues teaching about pointers, so be sure first to read Lesson 17: Pointers in C.

    http://visualcplus.blogspot.com/2006/03/lesson-17-pointers-in-c.html

  2. Anonymous Mortis 

    A comment I have on your terminology is the use of the word "reference" since this confuses with C++-references (as in pass-by-reference).

  3. Anonymous paulique ladao 

    can u please help us to make a SOURCE code or a basic program about STACKS AND QUEUES

Leave a Reply

      Convert to boldConvert to italicConvert to link

 


German Flag Spanish Flag French Flag Italian Flag Portuguese Flag Japanese Flag Korean Flag Chinese Flag British Flag


This Website is optimized for Firefox. Users browsing with Internet Explorer may encounter problems while viewing pages.


C++ Maniac



Learn C



Additional



#include



Learn Converting



Appendix


Links


Previous posts




Daily Lessons for programming in Visual Studio, using C code.