3

This might have been discussed before. But I couldn't find any reference so far. So thought to post it.

When we declare pointer (say of int type) we write,

int* pointer;

Where int* is data type (And therefore we can do typedef int* PTR_TO_INT; and then can declare variables of type PTR_TO_INT)

But when we want to declare multiple pointers, why do we need to affix * to each of them?

int* pointer1, pointer2, pointer3; // Only first is pointer. Rest are integers

While in this case it's not same convention:

PTR_TO_INT pointer1, pointer2, pointer3; // All are pointers.

Example:

int _tmain(int argc, _TCHAR* argv[])
{
    typedef int* PTR_MYINT;
    PTR_TO_INT xyz, abc;
    int* xyz1, abc1;

    xyz = NULL;
    abc = xyz; // Valid, as both are pointers

    abc1 = xyz1; // Invalid, as abc1 is not pointer
    return 0;
}
Atul
  • 3,778
  • 5
  • 47
  • 87
  • 2
    In practice, don't use `PTR_TO_INT` and keep every `*` for pointer types. You really want to know at a glance if something is a pointer. So declaring a `typedef int* PTR_TO_INT;` makes your code unreadable – Basile Starynkevitch Sep 08 '15 at 10:05
  • possible duplicate of [In C, why is the asterisk before the variable name, rather than after the type?](http://stackoverflow.com/questions/398395/in-c-why-is-the-asterisk-before-the-variable-name-rather-than-after-the-type) – phuclv Sep 08 '15 at 10:23
  • 1
    @LưuVĩnhPhúc: this does ask about the seeming disparity with `typedef`s, so IMHO shouldn't be closed as a duplicate of the question you cite. – Tony Delroy Sep 08 '15 at 10:38
  • The usual convention in C is `int *ptr`. In contrast, the usual convention in C++ is `int* ptr`, largely because it fits better with other C++ syntax (such as references), even though both languages have the same rules for `*`. – ams Sep 08 '15 at 11:54
  • @ams: I have not done much in C++ lately. When did this change and why? – too honest for this site Sep 11 '15 at 00:39

4 Answers4

10

That is no "convention", but required by the syntax. The * binds to the right token (here: pointer1, not the left (here: int). This is the reason, "convention" is to write int *ip actually (as you write it when you dereference the pointer lateron to get the object it points to).

So

int *ip, i;

Are two variables: a pointer to int (ip) and an int (i).

If you need two pointers:

int *ip1, *ip2;

But it is often recommended for documentation purpose to have two lines with a comment:

int *ip1;   // the first pointer
int *ip2;   // points to the next element

Here the base-type is int. If you have a typedef

typedef int *IntPtr;

The defined type is a pointers to int already, so if you use that as the base-type for a declaration:

IntPtr ip1, ip2;

You get two pointers, because of the base-type as for the example above.

Warning: Such typedefs visually (i.e. to the programmer, not the compiler) hide the underlying pointer semantics. This is not only dangerous, but also missleading to the reader, as you always have to be aware of this. You should not do this in general. There are few exceptions, but they are for special use-cases only.


Note: Another way to see

int *ip;

is: *ip is of type int (object-type view).

too honest for this site
  • 12,050
  • 4
  • 30
  • 52
5

In a similar way to the associativity of the dereference operator * being from right to left, the * when being used to specifier a type binds strictly to the right, and not the left token.

So it's associated with the variable name, rather than the type specifier.

Hence you need to write int * pointer1, * pointer2, * pointer3; with spacing according to your personal taste.

Effectively the typedef circumvents this associativity.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
4

But when we want to declare multiple pointers, why do we need to affix * to each of them?

int* pointer1, pointer2, pointer3; // Only first is pointer. Rest are integers

It's ultimately a quirky decision made when C was first written, which was probably motivated by the convenience and concision of being able to create both variables of some type, and pointers to such variables, in the same line of code.

int x, *p_x = &x;

When you're writing code that uses a lot of variables, fairly evenly mixed between pointers and non-pointers, that concision and convenience benefit can add up. Like many things in C, the programmer has the option to be extremely terse, and different programmers might have differing views on whether that's good or bad.

With a typedef, you're explicitly creating a particular alias for a type, and you may not even want the user of the typedef to know whether it's ultimately a pointer or not. For example:

typedef ...something... Handle;
Handle h = awesome_library_init();
awesome_library_finito(h);  // never knew if handle was int, struct*...
                            // may differ on e.g. Linux vs Windows

When client programmer are thereby encouraged to perceive the type as some opaque by-value type, it would be confusing if...

Handle h1, h2;

...didn't create two identical variables of the same type.

Tony Delroy
  • 102,968
  • 15
  • 177
  • 252
-3

typedef binds the * to the int (like in math when you put brakets around something).

fjellfly
  • 388
  • 1
  • 13
  • @Olaf:I don't think that it's wrong. As I wrote, the code of course won't even compile, but what I wanted to show is how typedef is "working". So how do you think typedef is working as you claim this wrong? – fjellfly Sep 08 '15 at 09:54
  • There's little point in citing syntactic nonsense: agree with @Olaf – Bathsheba Sep 08 '15 at 09:55
  • What do you mean by "the code will not compile"? `int *pointer1, pointer2;` will compile without problem. It just does not declare what OP expects. See my answer how `typedef` comes into play. – too honest for this site Sep 08 '15 at 10:02
  • The "not compile" aimed to the code I wrote (and now removed). If you realy put brakets around it's just wrong code. I just used another way to write it down than you did. – fjellfly Sep 08 '15 at 10:06
  • You did not, as now three people told you. If you would have: please provide **compiling** code which supports your claim. – too honest for this site Sep 08 '15 at 10:12
  • I totaly agree with what you wrote in your answer. It's fine. I didn't want to express anything else. – fjellfly Sep 08 '15 at 10:17