Users Online

· Guests Online: 4

· Members Online: 0

· Total Members: 185
· Newest Member: meenachowdary055

Forum Threads

Newest Threads
No Threads created
Hottest Threads
No Threads created

Latest Articles

FAQ: C Advanced Pointers

FAQ (Frequently Asked Questions) >C Advanced Pointers
01 What is Pointer to Pointer in C Programming02 What is Declaration by Inference in C03 What is Pointer to function in C04 What are Callback Functions in C?
06 What are Jump Tables in C?07 Explain Command Line Arguments in C Programming with Examples08 How Command Line Arguments are Passed and Processed in C?09 Explain String Literal Operations Using Pointers in C Programming
01 What is Pointer to Pointer in C Programming
Question: What is Pointer to Pointer in C Programming?
Answer: A pointer is a variable that holds address, address of a variable of any basic types, address of a structure, address of an array or address of some other pointer variable. For example,

int val = 10;
int *pi = &val; /* pi is a pointer pointing to integer val */
int **ppi = π /* ppi is a pointer to pointer to int */
Can you figure out results of following statements?

val;
*pi;
**ppi;
val is simplest gives value 10. What about value of *pi? We initialized pi address of integer val. Therefore, pi is pointing to val and we know that indirection on a pointer to something is that thing.

*pi;
results 10. Similarly, ppi is pointing to pi, single indirection on ppi, i.e.


*ppi;
results pi which is pointer to val. Therefore, double indirection on ppi, i.e.

**ppi;
or equivalently,

*(*ppi);
or equivalently,

*(pi);

which is *pi; and this results 10.

Why do we ever need a pointer to pointer when simple assignment works? Actually, consider the instance of insertion of new value in the singly linked list, fragment of code I’ve written below for easy understanding,

/* let's insert new value in the ordered list */
void insert_value(Node **linkp, int new_value)
{
Node *new_node;
Node *current;

/*
* walk down the list to find appropriate place to insert
* the new value
*/
while ((current = *linkp) != NULL && current->data < new_value)
linkp = ¤t->link;
/* Let's allocate new node dynamically */
new_node = (Node *)malloc(sizeof(Node));

/* Let's confirm if new_node allocated successfully */
if (new_node == NULL) {
puts("ERROR: new_node allocation!");
exit(2);
}

/* write-in new_value into value field of new_node */
new_node->data = new_value;

/* Let's insert new_node into the list */
new_node->link = current; /* new_node points to current node */
*linkp = new_node; /* previous node points to new_node */
puts("**New value successfully added into the list!**\n");
}
Notice here that a simple variable is not known within the function scope and linkp which is pointer to pointer to type Node makes insertion easy and efficient.
Top
02 What is Declaration by Inference in C
Question: What is Declaration by Inference in C
Answer: Let’s try some examples of declaration of variables in C,

int x;
int *y;
Observe that x is declared to be an integer. What about *y? Expression *y is also an integer. We deduce from here that y is a pointer to integer. This assertion can be validated in C as,

int* x, y;
What are x and y, now? Let’s try them in a simple C program,

#include <stdio.h>

int main(void)
{
int* x = 10, y;

return 0;
}
What happens when you compile this program, it turns out with a warning,

warning: initialization makes pointer from integer without a cast
[enabled by default]


Notice here that despite the spacing, asterisk(*) is associated with x making it a pointer to int while y is an ordinary integer.

Try one more example,

int xyz(int, int);

xyz is a function which takes two integer arguments and returns an int.

Remember that rules for declaration by inference for reading declarations are the same as those for ordinary expressions.

We can try several other expressions using declaration by inference, as,

int (*f)(int, int);
int (*x[5])(char, char);
Well! If declaration by inference seems to be a confusing for complex declarations, you can apply the same rules for evaluation of declarations as there are for other expressions in C. There are no separate rules or separate syntax. Let’s figure out the above two complex declarations below,


int (*f)(int, int);
int (*x[5])(char, char);
Notice that in first declaration, we have two sets of parenthesis of which first one being grouping has higher precedence making f a pointer to function that takes two integers as arguments and returns an integer.

In second declaration, again grouping goes first, making x an array of pointers, then second set of parenthesis, a function call, evaluates and results x an array of pointers to functions which take two char type values and return int.

You can this way evaluate any complex declaration. Fortunately, there are programs called cdecl for c declarations and c++decl for c++ declarations, which don’t come pre-installed on Linux Machines, which convert between English and declarations. Below given link, you can use to download these programs.

http://www.ibiblio.org/pub/Linux/devel/lang/c/
Top
03 What is Pointer to function in C
This C Tutorial explains Pointer to function in C with example.
Just like pointer to integer, pointer to structure, pointer to node in a linked list, we can declare pointer to function. Again, just declaration isn’t enough. Like other pointers, pointer to function must be initialized before indirection can be performed on it. Also, make sure that function prototype is given prior to initializing pointer to function, for without compiler would be unable to check type of function whether agreed with type of pointer to function.

Let’s consider a simple C program with pointer to function,

/* ptr2fun.c -- program declares and accesses pointer to function */
#include <stdio.h>

int sum(int const, int const);

int main(void)
{
int add_val;
int (*p2f)(int const, int const) = ∑
/* p2f is a pointer to function sum */

/* calling function */


printf("sum of 5 and 5 is %d\n", sum(5, 5));
/* called by name */

printf("sum of 5 and 5 is %d\n", (*p2f)(5, 5));
/* indirection on p2f */

printf("sum of 5 and 5 is %d\n", p2f(5, 5));
/* using p2f pointer */

return 0;
}
int sum(int const x, int const y)
{
return x + y;
}
When program is run, output turns out as follows,

sum of 5 and 5 is 10
sum of 5 and 5 is 10
sum of 5 and 5 is 10

Now, we count on important points in the above program. Notice the initialization of p2f,

int (*p2f)(int const, int const) = ∑
/* p2f is a pointer to function sum */
we used addressof (&) operator to initialize p2f address of function sum(). Nevertheless, operator ‘&’ isn’t necessary. Actually, compiler converts function name into function pointer which specifies where in memory function is stored.

Then, we emphasized function call statements as,

sum(5, 5);
(*p2f)(5, 5);
p2f(5, 5);

Which of these statements is more efficient than others? Let’s see how these internally implement. First statement calls the function by name. Compiler, as we know, converts function name into function pointer which locates where function sum() is stored in memory. Then function call operator invokes and starts executing instructions at that address.

In second function call, indirection is performed on the p2f, which results in function name sum. Compiler now converts function name to function pointer and executes as above. Actually, indirection isn’t required here.

The third statement is more efficient as this is pointer to function and executes as above.

Now, where we require pointer to functions is where we need to pass functions as arguments to some other functions. Two most common applications are callback functions and jump tables. We’ll discuss them later.
Top
04 What are Callback Functions in C?
This C Tutorial explains Callback Functions in C with examples.
Callback function technique is useful where you need to write a function that’s able to perform several different functions at a point or can perform a function specified only by the caller. This technique requires to pass a pointer-to-function to another routine, which calls back the user function to perform some task. Function calls back user’s function is called callback function.

For example, suppose we have to write a program which has to deal with different Linked Lists with different value types and we have to search a given value of particular type in a Linked List with that type of value, say, search an integer in a Linked List with integers values, search a text string in a list with string values etc..

Of course, we can write one function each for searching a value of particular type in a list with that type of values and calling the appropriate function. For example,

To search an integer,

search_ints(root, 6);
To search a string,


search_str(root, "hello");
How beautiful would it be if we are able to write a function that can search value of any type. Here pointer-to-function plays role. Here, caller writes the required function and passes pointer to it as an argument to search function which calls back user’s function to perform the task. Also, we pass pointer to value rather than value and this is received into type void const * at called function’s side.

Let’s understand it using a program below,

/* callback.c -- program implements callback technique to search a linked
* list for a given value
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int compare_ints(void const *, void const *); /* function prototype */
Node *search_list(Node *, void const *, int (void const *, void const *));
/* prototype */

int main(void)
{
int (*compare)(void const *, void const *) = compare_ints;

int value, val2find;
int nodes; /* nodes count*/
Node **rootp; /* pointer-to-root */
Node *desired_node;

puts("\n**Program creates Singly Linked List**");
puts("**And allows users to perform various operations on the"
" list**\n");
puts("User, specify number of nodes in the list, in range 1"
" through some positive no.");
scanf("%d", &nodes);

/* let's create list with specified nodes */
rootp = create_sll(nodes);

printf("Let's insert %d integers in the list...\n", nodes);
insert_data(rootp);

puts("**Let's show up the list**");
show_list(rootp);

puts("Let's sort the list, in ascending order...");
sort_list(rootp);
puts("**Let's show up the list**");
show_list(rootp);

puts("**Let's use Callback() function**");
printf("User, enter an integer you want to see into the "
"Singly Linked List...\n");
scanf("%d", &val2find);

/* call to callback function */
desired_node = search_list(*rootp, &val2find, compare);

/* Let's confirm whether desired value is found or not */
if (desired_node != NULL)
puts("Desired value is found.");
else
puts("Desired value NOT found.");

return 0;
}

/* search_list() is a typeless callback function */
/*
* 3rd argument to search_list() is pointer-to-function, search_list()
* calls back this function to compare values
*/

Node *search_list(Node *node, void const *value, int compare(void const *,
void const *))
{
while (node != NULL) {
if (compare(&node->data, value) == 0)
break;
node = node->link;
}

return node;
}

/* compare_ints() compares the integers */
int compare_ints(void const *p2nv, void const *p2v)
{
if (*(int *)p2nv == *(int *)p2v)
return 0;
else
return 1;
}
/* sll_header.h -- here's contained all header declarations for a
* singly linked list
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct NODE {
struct NODE *link; /* ptr-to-self_ref_struct */
int data;
} Node;
Node **create_sll(const int); /* fun. returns ptr-to-root */
void insert_data(Node **);
void show_list(Node **); /* fun. shows up data in the list */
void sort_list(Node **); /* sorting list using selection sort */

#include "sll_op.c"
/*
* sll_operations.c -- here's contained all the definitions of
* different operations performed on a singly linked list
*/

Node **create_sll(const int nodes)
{
int i;
Node *current;
static Node *root;
Node **rootp = &root; /* ptr-to-root */

/* Let's allocate memory dynamically */
root = (Node *)malloc(nodes * sizeof(Node));

/* verify if dynamic allocation successful */
if (root == NULL) {
puts("Error: Not Enough Memory!");
exit(1);
}
else {
/* Create the list */
current = root;
/* current set to the start of dynamic allocation */

for (i = 1; i <= nodes; i++) {
if (i == nodes) {
current->link = NULL;
}
else {
current->link = current + 1;
current++;
}
}
printf("List with %d nodes created successfully!\n", nodes);
puts("");
}

return rootp;
}

/* insert_data() inserts data into successive nodes in the list */
void insert_data(Node **linkp)
{
Node *next = *linkp;
Node *current;

/* Write integers into the list */
do {
current = next;
scanf("%d", &(current->data));
next = current->link;
} while (current->link != NULL);
puts("");
}

/* show up data in the list */
void show_list(Node **linkp)
{
Node *next = *linkp;
Node *current;

/* Let's read data from the list */
do {
current = next;
printf("%d ", current->data);
next = current->link;
} while (current->link != NULL);
puts("\n");
}

/* sorting list using Selection Sort */
void sort_list(Node **linkp)
{
int temp;
Node *current = *linkp;
Node *next = current->link;

/* Let's sort the list by sorting values */
while (current->link != NULL) { /* Outer while loop terminates when */
/* there's no next node to current node in the list */
while (next != NULL) { /* Inner while loop */
/* sorts the current value */
if (current->data > next->data) {
/* swap the values */
temp = next->data;
next->data = current->data;
current->data = temp;
}
/* update the next value */
next = next->link;
}
/* current value is sorted */
/* update the current and next values */
current = current->link;
next = current->link;
}
}
Let’s run the program and analyse the output


**Program creates Singly Linked List**
**And allows users to perform various operations on the list**

User, specify number of nodes in the list, in range 1 through some
positive no.
5
List with 5 nodes created successfully!

Let's insert 5 integers in the list...
32
53
1
08
4556

**Let's show up the list**
32 53 1 8 4556
Let's sort the list, in ascending order...
**Let's show up the list**
1 8 32 53 4556

**Let's use Callback() function**
User, enter an integer you want to see into the Singly Linked List...
53
Desired value is found.

User, enter an integer you want to see into the Singly Linked List...
33
Desired value NOT found.
What if user wants to search a given string in a list with values as strings, now caller has to write a function to compare strings and passes pointer-to-it in search_list(). Let’s use string comparison function strcmp() and search_list() function becomes

/* compiler converts function name into pointer-to-function */
/* strcmp is pointer to strcmp() function */
void *search_list(Node *, Void const*, strcmp)
{
int result;
result = strcmp(node->data, "string to be searched");
if (result == 0)
break;
/* string in list */
}
So, we noticed that how pointer-to-function simplified search operation by calling just one search_list() function.
Top
06 What are Jump Tables in C?
This C Tutorial Explains Jump Tables in C with Examples.
Let’s consider another application of pointer-to-functions, Jump tables! A jump table is a special array of pointer-to-functions. Since, this is an array, and as we know that all array elements must be of same type, therefore, it requires that all functions must be of same type and all take same number and same type of parameters. Further, this technique can be used where different tasks could be represented by consecutive integers beginning with zero.

The another trick is to make sure that all function prototypes appear before jump table declaration. First step to create a jump table is to declare and initialize the jump table. For example,

/* function prototypes */
int add(int, int);
int sub(int, int);
int mul(int, int);
int divide(int, int);


/*jumptable declared and initialized */
int (*diff_oper[])(int, int) = {add, sub, mul, divide};
Then, call the operation in jumptable, providing values to arguments,


result = diff_oper[(operator)](op1, op2);
/* jumptables.c -- program shows how jumptable is used to perform basic
* calculator functions
*/
#include <stdio.h>

#define ADD 0
#define SUB 1
#define MUL 2
#define DIV 3

int add(int, int);
int sub(int, int);
int mul(int, int);
int divide(int, int);

int main(void)
{
int op1, op2;
int result;
char operator;

/*jumptable declared and initialized */
int (*diff_oper[])(int, int) = {add, sub, mul, divide};

puts("**Calculator Application**");

result = diff_oper[(ADD)](50, 20);
printf("ADD of %d and %d is: %d\n", 50, 20, result);

result = diff_oper[(SUB)](50, 20);
printf("SUB of %d and %d is: %d\n", 50, 20, result);
result = diff_oper[(MUL)](50, 20);
printf("MUL of %d and %d is: %d\n", 50, 20, result);

result = diff_oper[(DIV)](50, 20);
printf("DIV of %d and %d is: %d\n", 50, 20, result);

return 0;

}

int add(int a, int b)
{
return a + b;
}

int sub(int a, int b)
{
return a - b;
}

int mul(int a, int b)
{
return a * b;
}

int divide(int a, int b)
{
return a / b;
}
Output turns out as,

**Calculator Application**
ADD of 50 and 20 is: 70
SUB of 50 and 20 is: 30
MUL of 50 and 20 is: 1000
DIV of 50 and 20 is: 2

How about if u need to perform some 50, 100 different operations. Jumptable is wonderful, then! If you think you can do the same job using switch statement, of course, you can. But switch statement, then, would go very large.

Notice that above program could be modified to make more interacting one. So, wouldn’t you like to try?
Top
07 Explain Command Line Arguments in C Programming with Examples
This C Tutorial explains Command Line Arguments in C Programming with examples.
Linux system gives us a command environment where we execute commands to perform certain tasks. For example,

ls command lists files and directories in a directory
ll gives long listing of files and directories in a directory
Actually, such commands are programs. And we may or may not pass arguments to programs for specific needs.

How can we pass arguments to ours’ C programs? Well! We can pass arguments to a C program through command environment. These arguments go into program’s main() parameters. A C program’s main takes generally two arguments, these are, first an integer type and the other an array of pointers-to-char.

int main(int argc, char *argv[])
{
/* statements */
}
argc stands for argument’s count while argv contains argument values. These names haven’t any magic associated with them and you can use any of yours’ choice for them. argv[] array is terminated by a NULL string. Therefore, you can use either of two arguments to count on no. of arguments passed to a C program.

Consider the below given command, say, to compile a program named “cmd.c”,

gcc -o cmd cmd.c
./cmd -abc -def hello, command line" "you pass arguments to program"
"great"
Firstly, we compiled cmd.c to a binary file with name cmd then we run the binary file cmd together with several arguments. All the arguments including program name, any options beginning with dash ‘-‘ followed by strings are passed into main’s parameters of cmd.c. Arguments passed from the command into a program are called command-line arguments. Let’s see a simple C program processing command-line arguments,

int main(int argc, char *argv[])
{
while (*argv != NULL) {
printf("%s", *argv);
argv++;
}

return 0;
}
Notice that above program doesn’t do useful except it prints on the terminal arguments passed to it with the program name.
Top
08 How Command Line Arguments are Passed and Processed in C?
This C Tutorial explains how Command Line Arguments are Passed and Processed in C.
Let’s try to understand through a simple C program,

/* cmd_args.c -- how to pass and access command line arguments */
#include <stdio.h>

void process_cmd_args(char **);

int main(int argc, char *argv[])
{
puts("**Program processes Command Line Arguments**");
/* process cmd-line arguments */
/* process options and file names given as arguments on command */
process_cmd_args(argv);

return 0;
}

void process_cmd_args(char **string)
{
char opt;
/* skip the 1st string which is program name */
/* process any options begin with - */
while (*++string != NULL && **string == '-') {
/* process option */
while ((opt = *++*string) != '\0') {
switch (opt) {
case 'a': puts("a");
break;
case 'b': puts("b");
break;
case 'c': puts("c");
break;
default: puts("option not known");
break;
}
}
}
/* Process file names if there's any otherwise read from terminal */
if (*string == NULL)
puts("process_standard_input()");
else {
do {
puts("Processing File Argument.");

} while (*++string != NULL);
}

}

Output when above program executed with

# gcc -o cmd_args cmd_args.c
# ./cmd_args -ab -c -d “hello, world of Linux” “C programs”

**Program processes Command Line Arguments**
a
b
c
option not known
Processing File Argument.
Processing File Argument.
Top
09 Explain String Literal Operations Using Pointers in C Programming
This Tutorial Explains Different Operations Performed on String Literals Using Pointers in C Programming
A string literal is a sequence of characters terminated by null byte ‘0’. For example,

/* strlit_op.c -- program shows operations on string literals */
#include <stdio.h>
#define NAME "What is your name?"

int main(void)
{
char name[25] = "xyz";
char * const p2name = "abc";

"abc" += 1;
"abc" + 1;
"abc"[0];
"abc"[1];
"abc"[10];
*("abc" + 2);
*"abc";

return 0;
}
If you compile the above program, compiler saves copy of #define sting some where in the memory and set a pointer to it. Compiler also terminates the string with null terminator. What about name character array? It’s a pointer constant. And p2name? It’s also a pointer constant. Let’s try to figure out how expressions in above program evaluate to,

"abc" += 1;
It seems as if we add 1 to string literal “abc” and assigns it the result. What do you think, if you can figure it out. This statement is an error. Because value of string literal is a pointer constant. Like, for ex., exp.,

5 += 5; /* 5 is constant */
can’t be evaluated. Therefore, statement

"abc" += 1;
is invalid. Consider the following statement,

"abc" + 1;
Again we are trying to add 1 to the string literal “abc”. Sure, you can, this time, easily unravel this. Since, string literal “abc” is a pointer constant pointing to first character ‘a’. Type of “abc” is a pointer to char. Therefore, when you add 1 to “abc”, 1 is adjusted to type char * and added to pointer constant. This moves pointer to character ‘b’.

Take another exp.,

"abc"[0];


As we know that array name is a pointer constant pointing to first element of the array. Therefore, exp. “abc”[0] can be rewritten as

*("abc" + 0);
or even as

*"abc";
which results first character ‘a’ in the string “abc”. Let’s explore exp.

"abc"[10];
Let’s take an analogy to evaluate the above exp.,

int white[5]; /* white is an array of 5 integers */
What will happen if you attempt to access

white[10];
Surely, subscript value 10 takes you off the end of the array white. Hence, an undefined result. Similarly, in exp.,

"abc"[10];
you go out of bounds and therefore undefined result.


/* strlit_op.c -- program shows operations on string literals */
#include <stdio.h>

#define NAME "What is your name?"

int main(void)
{
char name[25] = "xyz";
char * const p2name = "abc";

//"abc" += 1;
printf("Result of "abc" + 1 is %cn", "abc" + 1);
printf("Result of *("abc" + 1) is %cn", *("abc" + 1));
printf("Result of "abc"[0] is %cn", "abc"[0]);
printf("Result of "abc"[1] is %cn", "abc"[1]);
printf("Result of "abc"[10] is %cn", "abc"[10]);
printf("Result of *("abc" + 2) is %cn", *("abc" + 2));
printf("Result of *"abc" is %cn", *"abc");

return 0;
}

Output of the above program is as follows,

<pre lang="C" cssfile="hk1_style">
Result of "abc" + 1 is
Result of *("abc" + 1) is b
Result of "abc"[0] is a
Result of "abc"[1] is b
Result of "abc"[10] is
Result of *("abc" + 2) is c
Result of *"abc" is a
Let’s see an application of string literal in a C program that converts an unsigned integer into equivalent hexadecimal representation,

/*
* strlit_app.c -- program converts unsigned values into hexadecimal
* number
*/
#include <stdio.h>

#define MINUS1 4294967295 /* unsigned representation of -1 */

/* uint_to_hex() is a recursive function */
void uint_to_hex(unsigned);

int main(void)
{
unsigned value;

puts("n**Program converts Unsigned int to Hexadecimal No.**n");
printf("User, enter an unsigned integer value or -1 to quit: ");
while (scanf("%u", &value) == 1 && value != MINUS1) {
/* call to uint_to_hex() */
uint_to_hex(value);
puts("");
printf("more conversions, enter unsigned integer or -1 to quit:");
}
puts("Thank You!");
return 0;
}

void uint_to_hex(unsigned value)
{
unsigned quotient;

quotient = value / 16;
if (quotient != 0)
uint_to_hex(quotient);

putchar("0123456789ABCDEF"[value % 16]);
}
Output of the program as follows,


**Program converts Unsigned int to Hexadecimal No.**

User, enter an unsigned integer value or -1 to quit: 54
36
more conversions, enter unsigned integer or -1 to quit: 12
C
more conversions, enter unsigned integer or -1 to quit: 8667
21DB
more conversions, enter unsigned integer or -1 to quit: 12
C
more conversions, enter unsigned integer or -1 to quit: 3232
CA0
more conversions, enter unsigned integer or -1 to quit: -1
Thank You!
Notice how easy it has become to convert unsigned values to hex exploiting string literal. Exp.

[value % 16]
in square parenthesis evaluates subscript in the exp.

"0123456789ABCDEF"[value % 16]
and then selected the corresponding character from the string before printed that.
Top
Render time: 0.29 seconds
7,458,125 unique visits