Tags:
create new tag
, view all tags
Ok, I'm reviewing events.c (from xc/programs/Xserver/dix, IIRC), and running into problems because I forget what, for example "->" means. I may even already have a note on WikiLearn, but how do I search for it? Hmm, Ok that might be easier than searching for "." — I'll just search for "->" (on WikiLearn or Google).

See:

Contents

C Syntax

Here are some sites I ran across as I tried to find "->". I have a vague recollection that "->" is similar to ".", except that "->" is used when a pointer is involved. Maybe that's enough for now? BTW, the search on WikiLearn found nothing of value, my Google query was [C -> syntax] (and it found way too much):

Ok, here's an understandable explanation (from Accessing Members of a Structure:

Each member of a structure can be used just like a normal variable, but its name will be a bit longer. To return to the examples above, member name of structure st_rec will behave just like a normal array of char, however we refer to it by the name

st_rec.name

Here the dot is an operator which selects a member from a structure.

Where we have a pointer to a structure we could dereference the pointer and then use dot as a member selector. This method is a little clumsy to type. Since selecting a member from a structure pointer happens frequently, it has its own operator -> which acts as follows. Assume that st_ptr is a pointer to a structure of type student We would refer to the name member as

st_ptr -> name

I probably want to translate that into my own words sooner or later, and, while I'm at that site, look for a similar explanation of "function pointer". (And, I should make an example of the "dereference the pointer and then use dot as a member selector" approach — it might help things sink in.)

Aside: (Based on another page at that site.) It's probably important to remember one reason why pointers are used, in passing parameters to functions, from Structures as Function Arguments:

A structure can be passed as a function argument just like any other variable. This raises a few practical issues.

Where we wish to modify the value of members of the structure, we must pass a pointer to that structure. This is just like passing a pointer to an int type argument whose value we wish to change.

If we are only interested in one member of a structure, it is probably simpler to just pass that member. This will make for a simpler function, which is easier to re-use. Of course if we wish to change the value of that member, we should pass a pointer to it.

When a structure is passed as an argument, each member of the structure is copied. This can prove expensive where structures are large or functions are called frequently. Passing and working with pointers to large structures may be more efficient in such cases.

Here's a page about pointers that's worth reviewing, and a few choice quotes:

Imagine that we have an int called i. Its address could be represented by the symbol &i. If the pointer is to be stored as a variable, it should be stored like this.

int *pi = &i;

int * is the notation for a pointer to an int. & is the operator which returns the address of its argument. When it is used, as in &i we say it is referencing i.

The opposite operator, which gives the value at the end of the pointer is *. An example of use, known as de-referencing pi, would be

i = *pi;

Take care not to confuse the many uses of the * sign; Multiplication, pointer declaration and pointer de-referencing.

And here's another portion of the same page, with my comments added (within /* */):

This is a very confusing subject, so let us illustrate it with an example. The following function fiddle takes two arguments, x is an int while y is a pointer to int. It changes both values.

fiddle(int x, int *y) { printf(" Starting fiddle: x = %d, y = %d\n", x, *y); x ++; (*y)++; printf("Finishing fiddle: x = %d, y = %d\n", x, *y); }

since y is a pointer, we must de-reference it before incrementing its value.

A very simple program to call this function might be as follows.

main() { int i = 0; int j = 0;

printf(" Starting main : i = %d, j = %d\n", i, j); printf("Calling fiddle now\n");. fiddle(i, &j); printf("Returned from fiddle\n"); printf("Finishing main : i = %d, j = %d\n", i, j); }

Note here how a pointer to int is created using the & operator within the call fiddle(i, &j);.

The result of running the program will look like this.

Starting main : i = 0 ,j = 0 Calling fiddle now Starting fiddle: x = 0, y = 0 Finishing fiddle: x = 1, y = 1 Returned from fiddle Finishing main : i = 0, j = 1

After the return from fiddle the value of i is unchanged while j, which was passed as a pointer, has changed.

To summarise, if you wish to use arguments to modify the value of variables from a function, these arguments must be passed as pointers, and de-referenced within the function.

Where the value of an argument isn't modified, the value can be passed without any worries about pointers.

Ok, I'm going to make myself a little table, see if this helps:

Given: int pi = &i; / In english: pi, a pointer to an integer, gets the address of i */

Four questions:

How do you express the: Answer Operation
value of i using i? i
value of i using pi? *pi de-referencing pi
address of i using pi? pi
address of i using i? &i referencing i

I don't know how practical this is, but can I extend the previous example to "double indirection"?

Given:

  • int pi = &i; / In english: pi, a pointer to an integer, gets the address of i */
  • int (??) ppi = π / ??? Is this a way to set up double indirection? */

Does that mean:

How do you express the: Answer Operation
value of i using i? i
value of i using pi? *pi de-referencing pi
value of i using ppi? **ppi double de-reference?
address of i using ppi? *ppi? ??
address of i using pi? pi
address of i using i? &i referencing i

Some operations:

The last three of these are only very slightly paraphrased from Chapter 17: Pointers and Arrays:

  • Increment i via the pointer: *pi = *pi + 1;
  • Store the value 4 into the memory location associated with i: i = 4;
  • Store the address of i into the memory location associated with ptr: ptr = &i;
  • Read the contents of memory at the address stored in ptr: *ptr; (not a complete statement, or ???)

Drill:

  • Referencing something gives you the address of it (use &)
  • De-referencing something something gives you the value of it (use *)

Think of other mnemonic phrases (like my old favorite "gets"):

  • Read *pi as "the value (contents?) of what pi points to" (I think "the contents of pi" could be nice, but it's too easy to forget the "indirection":
    • pi has an address and contents of that address
    • the contents of that address is the address of something else (in this case i)
    • *pi is the contents not of pi, but of that something else (which pi "points to")
  • Read &i as "the address of i" (that doesn't seem nearly confusing enough)

Should I (can I) put these in terms of assembly language statements? Yup, I suppose I could — I think I've seen it before, and I'll see if I can find it on the Internet somewhere.

These pages might help, but I haven't found the Rosetta Stone yet (Google search on [C pointer "assembly language"]:

Reiterating: *p deals not with the contents of p, but with the contents of what p points to. (Now, that's starting to sound like "indirection" that I keep hearing about.) Should I draw (an ASCII) sketch:

        _________         __________
     p | address |     i |          |
       |   of i  |       |   data   |
        ---------         ----------
AKA:      p, &i             *p, i

Dereferencing can be applied to any expression. All of these are legal:
  • *var contents of mem loc pointed to by var

  • **var contents of mem loc pointed to by memory location pointed to by var

  • *3 contents of memory location 3

Ok. Now, a pointer can also point to a structure:

struct sts { int n; int m; } ts; /* is the syntax right? */

sts tsp = ts; / is the syntax right? */

Then:

  • n in ts is ts.n or tsp->n
  • m in ts is ts.m or tsp->m

Right??

And, a pointer can point to a function (I think) — how define?

Given a function:

void increment (int *i) { *i = *i + 1; } /* is the syntax right? */

Function Pointers

(Much of the following, including unattributed quotes, is from www.function-pointer.org: The site dedicated to C and C++ Function Pointers. It looks like a useful site, and a good idea for a site. Unfortunately, I think they sometimes say "define a function" when they mean "declare a function".)

How do we create a function pointer?

Here are some real function declarations (IIUC) for function pointers to ordinary C functions or static C++ member functions:

int (*pt2Function) (float, char, char); // C int (TMyClass::*pt2Member)(float, char, char); // C++

And here's an alternate that's only valid in C++ (to non-static C++ member functions):

"The basic difference is that all pointers to non-static member functions need a hidden argument: The this-pointer to an instance of the class. Always keep in mind: These two types of function pointers are incompatible with each other."

"*Important note:* A function pointer always points to a function with a specific signature! Thus all functions, you want to use with the same function pointer, must have the same parameters and return-type!"

A common use of a function pointer is to select a particular function to be performed at run time — you might define functions plus, minus, multiply, and divide, then call the appropriate one at run time (based on the operator used, +, -, *, /) via the function pointer.

Other Tidbits

"An array name is essentially a pointer to the first element in the array 
 
 char word[10]; 
 char *cptr;"

"C passes arrays by reference — the address of the array (i.e., of the first element) is written to the function's activation record otherwise, would have to copy each element"

(Other things are passed by value, use pointers to pass by "reference".)

Notes

Contributors

  • () RandyKramer - 29 Apr 2003
  • If you edit this page: add your name here; move this to the next line; and if you've used a comment marker (your initials in parenthesis), include it before your WikiName.

Page Ratings

Edit | Attach | Watch | Print version | History: r4 < r3 < r2 < r1 | Backlinks | Raw View | Raw edit | More topic actions
Topic revision: r4 - 2003-04-30 - RandyKramer
 
  • Learn about TWiki  
  • Download TWiki
This site is powered by the TWiki collaboration platform Powered by PerlCopyright 1999-2017 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding WikiLearn? WebBottomBar">Send feedback
See TWiki's New Look