Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Proper way to read 'int * ptr=&x'

The following code is easily interpreted as

int x=4;
int *ptr;  // ptr is a pointer to an int
ptr=&x; // the address of x  is assigned to the pointer ptr

But the following equivalent code, may read misleadingly like

int *ptr=&x; //  the address of x is assigned to  *ptr, which is an integer

that is it seems to be interpreted as assigning the address of x to the pointed value *ptr (int *ptr )= &x The correct interpretation as the one when declaration and initialization are separated should be written something like int *(ptr = &x),to make evident that the assignment is to the pointer and not to the pointed location but this gives an error, why is that? And what is the best way to read and think of int *ptr=&x?

like image 877
some_math_guy Avatar asked Nov 17 '25 09:11

some_math_guy


2 Answers

This is, admittedly a weird part of C and it's mostly due to C's evolution.

In C's syntax, declarations aim to mirror use, so that after int *x;, *x resolves to an int and *x=42 assigns to that int. But initializations, which are started with = after the specifiers declarator part of a declaration, are syntactically and semantically different from an assignments.

(Initialization can "assign" to static/filescope variables and such an assignment generates no code: it simply contributes to the makeup of the resulting binary. Assignments always generate code unless optimizations can delete it)

Initializations and assignments used to be very differently looking in prehistoric C, where you'd initialize without the = sign as in int x 42;. (Even after the = was added to the syntax of initializations, it was long impossible to initialize local, nonstatic, variables which meant situations such as int *p = &x; didn't arise all that often.)

The old syntax had problems (would int x (42); also declare and initialize x or would it be a function declaration?) and that's why it was replaced, but I like how it emphasized that initializations are different from assignments.

Unfortunately with the new syntax (as in int x, *p = &x;) this distinction is not all that apparent, and you simply have to remember that when you have type specifiers (int) at the left end, then the = does not denote an assignment where you can just look at *p = &x but rather that it's an initialization where you have to look at the whole declaration and see what's declared (x as an int and p as a pointer to int) . The = in that context then initializes the declared identifier.

like image 168
PSkocik Avatar answered Nov 19 '25 01:11

PSkocik


int * is the type, so it makes perfect sense. It's just that pointer notation in C can take some effort to get used to. But look at this code

typedef int* int_ptr;
int x;
int_ptr ptr = &x;

Same thing. However, it's often advised to NOT typedef pointers.

The confusion comes from that * serves two roles. It is BOTH to name a type AND to dereference a pointer. An example of the first is sizeof(int*)

If you declare several pointers at once it looks messier, but it's still the same. In general, it's recommended to not declare more than one pointer at once. Because if we would like to do the above thing with two pointers, it would look like this:

int *pa = &x, *pb = &x;

That's the same as

int *pa = &x;
int *pb = &x;

And this does something completely different and will generate a warning because you're assigning the address of a variable to the pb variable that has type int

int *pa = &x, pb = &x;

However, using the typedef from above, you can (but probably shouldn't) do this:

int_ptr pa=&x, pb = &x;

But one way to think of it is that it makes no sense at all in any situation to dereference an uninitialized pointer.

And what is the best way to read and think of int *ptr=&x?

Take the fact that it does not make sense to dereference an uninitialized pointer. And you're doing an initialization of a pointer, and therefore you should initialize it with a (valid) address.

Ok, I see that, another thing. If the type is int* why is it almost always written like with the * next to the pointer variable instead, like int *ptr?, it would make more sense, even if it is the same to write it like int* ptr.

Because, then it would be MUCH easier to forget the asterisk if you declare several pointers at once. That would give the impression that int* p,q; declares two pointers.

C pointer syntax is clunky. It's a very old language. Just get used to it. It will never change. Just for fun, here is a page that can tell what a declaration is https://cdecl.org/ so try these:

int (*p)[3]
int *p[3]
const int *p[3]
int *const p[3]
const int (*p)[3]
int (*const p)[3]
like image 32
klutt Avatar answered Nov 18 '25 23:11

klutt