I recently developed an interest in C programming so I got myself a book (K&R) and started studying.
Coming from a University course in Java (basics), pointers a
Pointers make it possible to dynamically dispatch code given conditions or state of the program. A simple way of understanding this concept is to think of a tree structure where each node represents either a function call, variable, or a pointer to a sublevel node. Once you understand this you then use pointers to point to established memory locations that the program can reference at will to understand the intitial state and thus the first dereference and offset. Then each node will contain it's own pointers to further understand the state whereby a further dereference can take place, a function can be called, or a value grabbed.
Of course this is just one way of visualizing how pointers can be used since a pointer is nothing more than an address of a memory location. You can also use pointers for message passing, virtual function calls, garbage collection, etc. In fact I have used them to recreate c++ style virtual function calls. The result is that the c virtual function and c++ virtual functions run at the exact same speed. However the c implementation was much smaller in size (66% less in KB) and slightly more portable. But replicating features from other languages in C will not always be advantageous, obviously b/c other languages could be better equipped to gather information that the compiler can use for optimization of that data structure.
In summary there is a lot that can be done with pointers. The C language and pointers are devalued nowadays b/c most higher level languages come equipped with the more often used data structures / implementations that you would have had to build on your own with the use of pointers. But there are always times when a programmer may need to implement a complex routine and in this case knowing how to use pointers is a very good thing.
In this example:
int f1(int i);
f1(x);
the parameter i
is passed by value, so the function f1
could not change the value of variable x
of the caller.
But in this case:
int f2(int* i);
int x;
int* px = &x;
f2(px);
Here we still pass px
parameter by value, but in the same time we pass x
by refference!. So if the callee (f2
) will change its int* i
it will have no effect on px
in the caller. However, by changing *i
the callee will change the value of x
in the caller.
Ignore that answer please.
If you don't know how to use pointers, learn how to use them. Simple.
Pointers as you say allow you to pass more than one variable into a function via a pointer to it, as you have rightly observed. Another use of pointers is in referring to arrays of data, which you can step through using pointer arithmetic. Finally, pointers allow you allocate memory dynamically. Therefore advising you don't use pointers is going to severely limit what you can do.
Pointers are C's way to talk about memory addresses. For that reason, they are critical. As you have K&R, read that.
For one example of usage, see my answer to this. As I say in that answer, it isn't necessarily how you'd do it, given the question.
However, that technique is exactly how libraries like MPIR and GMP work. libgmp if you haven't met it powers mathematica, maple etc and is the library for arbitrary precision arithmetic. You'll find mpn_t
is a typedef to a pointer; depending on the OS depends on what it points to. You'll also find a lot of pointer arithmetic in the slow, C, versions of this code.
Finally, I mentioned memory management. If you want to allocate an array of something you need malloc
and free
which deal with pointers to memory spaces; specifically malloc
returns a pointer to some memory once allocated or NULL
on failure.
One of my favourite uses of pointers yet is to make a C++ class member function act as a thread on windows using the win32 API i.e. have the class contain a thread. Unfortunately CreateThread
on windows won't accept C++ class functions for obvious reasons - CreateThread
is a C function that doesn't understand class instances; so you need to pass it a static function. Here's the trick:
DWORD WINAPI CLASSNAME::STATICFUNC(PVOID pvParam)
{
return ((CLASSNAME*)pvParam)->ThreadFunc();
}
(PVOID is a void *
)
What happens is it returns ThreadFunc
which gets executed "instead of" (actually STATICFUNC calls it) STATICFUNC
and can indeed access all the private member variables of CLASSNAME
. Ingenious, eh?
If that isn't enough to convince you pointers kinda are C, I don't know what is. Or maybe there's no point in C without pointers. Or...
Coming from Java, you'll have a slightly different perspective than what is presented in K&R (K&R doesn't assume that the reader knows any other modern programming language).
A pointer in C is like a slightly more capable version of a reference in Java. You can see this similarity through the Java exception named NullPointerException
. One important aspect of pointers in C is that you can change what they point to by increment and decrement.
In C, you can store a bunch of things in memory in an array, and you know that they are sitting side by side each other in memory. If you have a pointer to one of them, you can make that pointer point to the "next" one by incrementing it. For example:
int a[5];
int *p = a; // make p point to a[0]
for (int i = 0; i < 5; i++) {
printf("element %d is %d\n", i, *p);
p++; // make `p` point to the next element
}
The above code uses the pointer p
to point to each successive element in the array a
in sequence, and prints them out.
(Note: The above code is an expository example only, and you wouldn't usually write a simple loop that way. It would be easier to access the elements of the array as a[i]
, and not use a pointer there.)
Remember that C (and the K&R book) very old, probably older than anything you've learned before (definitely ages older than Java). Pointers aren't an extra feature of C, they're a very basic part of how computers work.
Pointer theory isn't particularly hard to master, just that they're very powerful so an error will most likely crash your application, and compilers have a hard time trying to catch pointer-related errors. One of the big novelties about Java was to have 'almost' as much power as C without pointers.
So, in my opinion trying to write C avoiding pointers is like trying to ride a bike without one pedal. Yes, it's doable but you'll work twice as hard.