C Pointer, struct Pointer, function Pointer Made Simple ByZ.Haque
1
Pointers in C
Pointers in C can be very confusing and may cause frustration while programming in C. Improper use of pointers often cause memory leak, coredump and system crush. The intend of the document to make pointers as simple as possible. Pointers are not rocket science, any one can gain in depth understanding about pointers easily. A pointer is a variable that holds the address of other variable or constant value. Therefore, a pointer must be initialized to a variable or a constant. A pointer contains garbage until it is initialized. Since compilers cannot detect uninitialized or wrongly initialized pointers, the errors may not be known until we execute the program. If a pointer points to the address of a constant value, storage space must be allocated using malloc function so that the constant value has an address. If a variable is declared, the storage space and address of the storage space is automatically created by compiler. So there is no need to malloc. The following C program demonstrates use of pointers: #include <stdio.h> int main() { int a = 50; int *x, *y; int **pp;
/* a is a variable */ /* x and y are pointers to integer */ /* pp is pointer to pointer */
/* Method I: assign address of a variable to pointer x */ x = &a; /* x is assigned the address of a */ printf("The value of a: %d address of a =%p %X %X\n",a,x,x,&a); /* Method II: allocate memory and assign the address to a pointer */ y = (int *)malloc(sizeof(int)); *y = 60; printf("The value = %d address of it =%p %X %X\n",*y,y,y,y); /* pp can only be assigned the address of a pointer */ pp = &x; printf("The value of a: %d address of a =%p %X %X\n",**pp,pp,pp,&x); /* a pointer can be assigned to other pointer */ x = y; /* x and y point to the same variable */ printf("The value = %d address of it =%p %X %X\n",*y,y,y,y); return 0; } Output: The value The value The value The value
of a: 50 address of a =2ff22720 2FF22720 2FF22720 = 60 address of it =20000648 20000648 20000648 of a: 50 address of a =2ff22724 2FF22724 2FF22724 = 60 address of it =20000648 20000648 20000648
Pointer to pointer Pointer to pointer notation is **. A pointer to pointer can only point to another pointer or in other words, a pointer to pointer can only be assigned a value via another pointer. The following example illustrates this:
C Pointer, struct Pointer, function Pointer Made Simple ByZ.Haque
2
#include <stdio.h> /********************************** * pointer to pointer illustration * +-----+ +-----+ +-----+ * | | | | | | * | p |-->| *p |-->| 90 | * | | | | | | * +-----+ +-----+ +-----+ * p can only to a pointer (*p), * *p can point to int *******************************/ int main() { int **p; p = (int **)malloc(sizeof(int *)); *p = (int *)malloc(sizeof(int)); **p = 90; printf("Value=%d address of *p=%p and p=%p\n", **p,*p,p); free(p); free(*p); return 0; }
C struct and Pointers Whenever you use pointers make sure that you allocate memory first before using them, C struct is not an exception. The following examples illustrate the use of pointers in C struct. The examples are self explanatory. In the example, address of the variable lineIndex is assigned to *index pointer, so there was no need to malloc. #include <stdio.h> #include <malloc.h> /* Method 1: If a struct has a pointer member, memory must be allocated * using malloc before assigning any value to it. */ struct line { Int lineNumber; char lineName[80]; int *index; }; main() { int lineIndex = 10; struct line *linPtr; linPtr = (struct line *)malloc(sizeof(struct line)); linPtr->index = &lineIndex; printf("Line index=%d\n",*(linPtr->index)); free(linPtr); }
C Pointer, struct Pointer, function Pointer Made Simple ByZ.Haque If you assign a pointer to a pointer, make sure that you allocate memory, otherwise you get memory leak (coredump). The following example illustrates that: #include <stdio.h> #include <malloc.h> struct line { int lineNumber; char lineName[80]; int *index; }; main() { int lineIndex = 10, *pi; struct line *linPtr; pi = &lineIndex; linPtr = (struct line *)malloc(sizeof(struct line)); linPtr->index = pi; printf("Line index=%d\n",*(linPtr->index)); free(linPtr); }
If you want to assign the address of a constant value to pointer member of the struct, you must allocate memory first for both the struct, and the pointer member ( very important). The following example illustrates that:
#include <stdio.h> #include <malloc.h> /* Method 2: Allocate memory for both struct and pointer member. */ struct line { int lineNumber; char lineName[80]; int *index; }; main() { int lineIndex = 10; struct line *linePtr; linePtr = (struct line *)malloc(sizeof(struct line)); linePtr->index = (int *) malloc(sizeof(int)); *(linePtr->index) = 10; printf("Line index=%d\n",*(linePtr->index)); free(linePtr); }
3
C Pointer, struct Pointer, function Pointer Made Simple ByZ.Haque The following example illustrates the dot and arrow notation of a struct pointer. #include <stdio.h> #include <malloc.h> struct rec { int i; float f; char c; }; int main() { struct rec *p; p=(struct rec *) malloc (sizeof(struct rec)); (*p).i=10; /* *p.i does not work, . higher precedence, so use () */ (*p).f=3.14; (*p).c='a'; printf("\nDot notation: %d %f %c\n",(*p).i,(*p).f,(*p).c); printf("Arrow notation: %d %f %c\n\n",p->i,p->f,p->c); free(p); return 0; }
Nested struct Pointers If you have nested struct make sure that you allocate memory for all of them. The following example illustrates this:
#include <stdio.h> #include <malloc.h> struct line { int lineNumber; char lineName[80]; }; struct line myline = { 10, "This is my line." }; struct page { struct line *linePtr; int pageNumber; }; main() { struct page *pagePtr; struct line *linePtr; pagePtr = (struct page *)malloc(sizeof(struct page)); linePtr = (struct line *)malloc(sizeof(struct line)); pagePtr->linePtr = &myline; printf("Line =%d %s\n",pagePtr->linePtr->lineNumber, pagePtr->linePtr->lineName); } Output: Line =10 This is my line.
4
C Pointer, struct Pointer, function Pointer Made Simple ByZ.Haque Passing struct pointer as parameter The following examples illustrate the struct pointer as parameter to a function. Pointer to my_struct is passed to show_name function and pointer to pointer is passed to show_me function.
#include <stdio.h> #include <string.h> struct my_struct { char lname[20]; char fname[20]; int age; }; struct my_struct myStruct; void show_name(struct my_struct *p); void show_me(struct my_struct **p); int main(void) { struct my_struct *st_ptr; st_ptr = &myStruct; strcpy(myStruct.lname,"John"); strcpy(myStruct.fname,"Citizen"); myStruct.age = 25; printf("\nN = %s ",myStruct.fname); printf("%s ",myStruct.lname); printf("%d\n",myStruct.age); show_name(st_ptr); /* pass the pointer */ /* pointer to pointer passed */ show_me(&st_ptr); /* pass the pointer to pointer */ return 0; } void show_name(struct my_struct *p) { /* arrow notation */ printf("\n P1 = %s ", p->fname); printf("%s ", p->lname); printf("%d\n", p->age); /* dot notation */ printf("\n P2 = %s ", (*p).fname); printf("%s ", (*p).lname); printf("%d\n", (*p).age); } void show_me(struct my_struct **p) { printf("\n PP1 = %s ", (*p)->fname); printf("%s ", (*p)->lname); printf("%d\n", (*p)->age); printf("\n PP2 = %s ", &(*p)->fname); printf("%s ", &(*p)->lname); printf("%d\n", &(*p)->age); printf("%d\n", (*p)->age); printf("\n PP2 = %s ", (**p).fname); printf("%s ", (**p).lname); printf("%d\n\n", (**p).age); }
5
C Pointer, struct Pointer, function Pointer Made Simple ByZ.Haque
6
Struct pointer to pointer as parameter. The following example shows struct pointer as parameter to a complex nested struct: #include <stdio.h> #include <malloc.h> struct line { int lineNumber; char lineName[80]; }; struct line myline = /* Assign some values to line struct */ { 10, " This is my line." }; struct page { struct line *linePtr; int pageNumber; }; struct book { struct page *pagePtr; int bookNumber; }; int myfun (struct book **bPtrPtr, struct line *lPtr) { *bPtrPtr = (struct book *) malloc(sizeof(struct book)); (*bPtrPtr)->pagePtr = (struct page *) malloc(sizeof(struct page)); (*bPtrPtr)->pagePtr->linePtr = (struct line *) malloc(sizeof(struct line)); (*bPtrPtr)->pagePtr->linePtr = lPtr; printf("Inside myfunc: Line %d %s\n",(*bPtrPtr)->pagePtr->linePtr->lineNumber, (*bPtrPtr)->pagePtr->linePtr->lineName); } main() { struct book *bookPtr; struct line *linePtr; myfun(&bookPtr,&myline); printf("In main: Line %d %s\n",bookPtr->pagePtr->linePtr->lineNumber, bookPtr->pagePtr->linePtr->lineName); } Output: Inside myfunc: Line 10 This is my line. In main: Line 10 This is my line.
Function returns a pointer A function can return a pointer. You ensure that you allocate memory for pointer, otherwise you get coredump. The following example illustrates:
C Pointer, struct Pointer, function Pointer Made Simple ByZ.Haque
7
#include <stdio.h> int *sum(int *i, int *j) { int *r; r = (int *) malloc(sizeof(int)); *r = *i + *j; return r; } main() { int x=20, y=30; int *result; result = sum(&x, &y); printf("Sum is %d\n", *result); }
Function pointers Function pointer sounds very complex, but it’s not. Please read the following phrase: Never fear big long words. Big long words mean little things. All big things have little names, Such as life and death, peace and war, Or dawn, day, night, hope, love, home. Learn to use little words in a big way. It is hard to do, But they say what you mean. When you don't know what you mean, Use big words-That often fools little people. -- Arthur Kudner
Function pointer is just like any other pointer but holds the address of a function. So the function name can be changed run time. In the following example, we have two functions max and min and a function foo which has one of the parameter called function pointer. So we can choose max or min as parameter to foo function at run time. While calling replace the function pointer with only the function name. So simple is that illustrated below:
C Pointer, struct Pointer, function Pointer Made Simple ByZ.Haque #include <stdio.h> /* returns max number */ int max(int a, int b) { return (a > b ? a : b); } /* returns smallest number */ int min(int x, int y) { return (x < y ? x : y); } /* foo takes two inputs and a function pointer as parameter * and returns an integer. As a function pointer, you can * pass either max or min */ int foo(int a, int b, int (*funPtr) (int p1, int p2)) { return funPtr(a, b); }
int main(int argc, char *argv[]) { int result; if(argc < 3) { printf("Error: usage: fp max 22 52\n"); exit(0);} int x = atoi(argv[2]); int y = atoi(argv[3]);
if(strcmp(argv[1],"max") == 0) { result = foo(x, y, max); printf("\nmax of %d and %d is =%d\n\n", x, y, result); } else { result = foo(x, y, min); printf("\nmin of %d and %d is =%d\n\n", x, y, result); } return 0; } Output: $ a.out min 400 55 min of 400 and 55 is =55
8
9 C Pointer, struct Pointer, function Pointer Made Simple ByZ.Haque Here is an another example of Function Pointers. Although it looks complex in declaration, the function pointer is simply replaced by the function name. #include <stdio.h> #include "worker.h" void do_fiveTimes(int *job_vp) { printf("In do_fiveTimes input param = [%d]\n", *job_vp); /* White whatever you want it to do */ /* for simplicity I just multiply 5 */ *job_vp = (*job_vp) * 5; printf("In do_fiveTimes output = [%d]\n", *job_vp); } void do_twoTimes(int *result_vp) { printf("In do_twoTimes input param = [%d]\n", *result_vp); /* White whatever you want it to do */ /* for simplicity I just multiply 2 */ *result_vp = (*result_vp) * 2; printf("In do_twoTimes output = [%d]\n", *result_vp); } int run_input_output( void (do_fiveTimes)(int *), void (do_twoTimes)(int *), int *context_vp) { int result_vp; do_fiveTimes(context_vp); do_twoTimes(context_vp); } main(int argc, char *argv[]) { int ret_val; if(argc < 2) { printf("Usage: a.out 9\n"); exit(0);} int x = atoi(argv[1]); do { ret_val = run_input_output( do_fiveTimes, /* just write function name w/o param */ do_twoTimes, /* just write function name w/o param */ &x /* here is parameter */ ); if(ret_val < 0) break; printf("In main result = [%d]\n", x); } while (0); printf("Program successfully completed.\n\n"); } Output: a.out 8 In do_fiveTimes input param = [8] In do_fiveTimes output = [40] In do_twoTimes input param = [40] In do_twoTimes output = [80] result = [80] Program successfully completed.
10 C Pointer, struct Pointer, function Pointer Made Simple ByZ.Haque All the programs in this document have been testing and working. However, author does not take any responsibilities in any form either implied or written if any of the programs breaks your hardware or software or both or your marriage or relationship. Use them at your own risk. Yours comments are welcome. If you have destructive comment, re-direct it to else where. If you have constructive comment or question, send it to me.