views:

221

answers:

7

hi,

Just getting into C++. I'm getting constantly thrown off track when I see the symbol for multiply (*) being used to denote the dereferencing of a variable

for example: unsigned char * pixels = vidgrabber.getPixels();

Does this throw other people off? What's the tip for getting my head around this?

Thank you.


p.s. I have another reasonably simple question, that didn't get answered :( here: beginner question: add/subtract to value rather than just be that value pretty please! and thanks for your time!

A: 

You can distinguish the dereference operator from the multiplication operaotr by the fact that, usually, a multiplicator operator doesn't have a type name on his left.

klez
+9  A: 

C, and by inheritance C++, are swamped with operators and are inherently context-sensitive. You will have to get used to it:

If * appears before the name of a variable that is being declared (or defined), it's a type modifier and makes that variable a pointer.
If it is a unary prefix operator for a variable that is part of an expression, it's dereferencing (or whatever it's been overloaded to).
If it is a binary infix operator for two variables that are part of an expression, it's multiplication (or whatever it's been overloaded to).

(From this you can see that the * in your unsigned char * pixel isn't a dereferencing unary prefix, but a type modifier.)

Note that & pretty much resembles *, only it's meaning is different: it makes a variable a reference, is the address-of operator, or the binary AND.

sbi
+1 for a good answer to the generalization of this question as well as this question itself. I particularly like 'context-sensitive'
Cam
Arun
@Arun: I'm not sure what you're expecting.
sbi
+6  A: 

One recommendation when writing your own code is to "cuddle" the * when using as a pointer/deref:

unsigned char *pixels = ...

if (*pixels == ...)

and to space the * when using as a multiply:

int y = x * 7;

There are other clues you can use (such as the fact that pointer deref is a unary operator while multiple is a binary operator).

R Samuel Klatchko
+2  A: 

The answer is: practice. Every new programming language will look funny to some extent, some funnier than others. Learn to use it and it will become natural.

David Thornley
+1  A: 

Contrived Example

You wrote about dereferencing in C. Can you tell the result from just looking at it? ==>

int v[] = {5,6}, w[] = {7,8};
int m[][2] = { {1,2}, {3,4} };

int result = * v * * * m * * w;

Regards

rbo

rubber boots
The meaning of `* v * * * m * * w` is that the cat's been up on the keyboard again. (It does that a lot when it's fighting for attention.)
sbi
Great answer! A beginner who's new to pointers will surely benefit from this.
Cam
Off the top of my head I think "* * m" is going to produce something wonky.. *m is 1, but **m the contents of memory address 0x00000001 which could be anything on some platforms. Anyway, whatever that is, the result will be that times 35.
Sparr
There can always be only one multiplicator after a variable, all others are dereferences. So just follow the advice to keep dereferences close (= no space) to the variable, so it changes to`int result = *v * **m * *w` and solution is quite simple.
IanH
@Sparr: I thought, damn you're right (and thus my answer wrong), but disassembly proves you wrong.
IanH
A: 

The same way English speakers get around the fact that the same word can have different meanings depending on the context. Once you are somewhat immersed in the context, it will usually be obvious what the operator is doing.

JohnMcG
+1  A: 

An important thing to note about C compared with other languages is that in when multiple declarations are combined in one statement, the asterisk applies to individual items, not the set as a whole. For example:

int* foo,bar;

creates an int-pointer called foo, and an int called bar. I always peg the asterisk to the variable, and I avoid mixing pointers and non-pointers in one statement thus:

int *foo;
int *ptr1,*ptr2,*ptr3;
int bar,boz,baz;

It's also important to note that storage-class qualifiers like 'const' and 'volatile' may not always bind as one would expect. The statement

volatile int *foo;
does not mean that 'foo' is a volatile, but rather that what 'foo' points to is a volatile. If foo itself is the 'volatile' thing, one must write "int * volatile foo;"

supercat