The stack is a contiguous section of memory set aside for a program.
A stack frame, sometimes known as an activation record, is created and pushed onto the stack whenever we invoke a function. Typically the stack frame consists of the return address back to the calling function, and a set amount of space for all of the parameters and local variables. When the function returns, its stack frame is removed from the stack.
When a stack frame is created, the parameters are copied into the frame in the opposite order set in the parameter list. All parameters are passed by value, which is to say a copy is made of the data and assigned to a memory location in the stack frame. Even we pass a value by reference in C using pointers, we are still making a copy of the data, it just so happens that the data being copied is the memory address of the actual variable, structure, etc we wish to manipulate.
#include <stdio.h>
void func1(int *i);
int main(void){
int a = 10;
int *intPtr = &a;
printf("intPtr holds memory address %p\n", intPtr);
printf("which points to a variable holding the value %d\n", *intPtr);
printf("and is located at %p\n", &intPtr);
//call the function
func1(intPtr);
return 0;
}
void func1(int *i){
printf("func1 parameter i holds the memory address %p\n", i);
printf("which points to a variable holding the value %d\n", *i);
printf("but it is located at %p\n", &i);
}
The thing to remember here is that all parameters, including pointers, are passed by value.
Passing pointers to functions allows the referenced data to be accessible without having to duplicate the data or make it a global variable. By passing pointers to data rather than the data itself, we can modify the data the in the function and have the modification persist beyond the life of the called function.
#include <stdio.h>
void swap(int *iPtr01, int *iPtr02);
int main(void){
int i = 404;
int j = 711;
printf("i = %d, j = %d\n", i, j);
swap(&i, &j);
printf("i = %d, j = %d\n", i, j);
return 0;
}
void swap(int *iPtr01, int *iPtr02){
int localVar;
localVar = *iPtr01;
*iPtr01 = *iPtr02;
*iPtr02 = localVar;
}
We cannot modify a value passed as a pointer to a constant. Passing a pointer to a constant thus allows us to pass a reference to data without having to copy all of the data to the function, while not having to worry about the data being pointed to being modified.
#include <stdio.h>
void CannotModify(const int *ip);
void CanModify(int *ip);
int main(void){
int i = 42;
CanModify(&i);
CannotModify(&i);
return 0;
}
void CannotModify(const int *ip){
printf("Value = %d\n", *ip);
}
void CanModify(int *ip){
//increment value pointed to
(*ip)++;
}
To return a pointer from a function is simple enough, but we must remember to allocate the memory the pointer will point to using malloc(), so that it will be allocated on the heap, and not the stack.
#include <stdio.h>
#include <string.h>
#include <malloc.h>
double * doubleValue();
char * getString(int length);
int main(void){
double *trouble = doubleValue();
char *str = getString(50);
strcpy(str, "You have failed us, Torgo. For this, you must die!");
printf("%s\n", str);
//don't forget to free the memory
free(str);
free(trouble);
return 0;
}
double * doubleValue(){
double *dare = (double*)malloc(sizeof(double));
return dare;
}
char * getString(int length){
char *s = (char*)malloc(++length * sizeof(char));
return s;
}
When a function returns a pointer to dynamically allocated memory, it is the calling function’s responsibility to deallocate the memory when it is done with it.
As stated earlier, when a pointer is passed a function, it is passed by value. This means that if we want to modify the pointer itself, and not the parameter pointer, we must pass a pointer to the pointer.
#include <stdio.h>
#include <malloc.h>
#include <string.h>
void allocateDouble(double **d, double val);
void allocateString(char **s, char *val);
int main(void){
double *dare;
char *statement;
allocateDouble(&dare, 19.99);
allocateString(&statement, "Nice Boat!");
printf("%s\n", statement);
return 0;
}
void allocateString(char **s, char *val){
int length = strlen(val);
*s = (char*)malloc(length * sizeof(char));
strcpy(*s, val);
}
void allocateDouble(double **d, double val){
*d = (double*)malloc(sizeof(double));
}
if you are interested in learning C, take a look at by book available at: http://www.amazon.com/Big-Als-C-Standard-ebook/dp/B00A4JGE0M/