简体   繁体   中英

How can a C pointer of type int hold a memory address, given that a byte memory address is not of type int?

I was looking at an answer to "Pointers in C: when to use the ampersand and the asterisk" and am confused about the example int *p2 = &i; (from Dan Olson's answer)

The address of i is not an int, it's something like 0x02304 say, right? So how can we put this into p2 ? How can a C pointer of type int hold a memory address, given that a byte memory address is not of type int?

Thanks!

PS For anyone confused on this point, another thread I found helpful (though it didn't answer this question for me) is "What exactly is a C pointer if not a memory address" Good luck.

The address of i is not an int, it's something like 0x02304 say, right?

Pointers are variables that hold memory addresses. An address, just like the address of your house, is an integer assigned to the location of a byte of memory.

How can a C pointer of type int hold a memory address

In your example, p2 is variable of type pointer-to-int . It is a pointer - a memory address - that you're declaring points to memory where an int variable will be stored.

p2 is not an int , it is a pointer to int . As such, it can hold the address of an int variable.

The syntax int *p2; defines a pointer to int .

Initializing p2 with &i stores the address of variable i into p2 . Modifying the value pointed to by p2 will modify the value of i .

The following alternative syntaxes are all equivalent:

int *p2 = &i;
int * p2 = & i;
int * p2 =& i;
int*p2=&i;
int* p2 = &i;

The preferred syntax is int *p2 = &i; because it avoids a common misunderstanding when defining multiple variables on the same line:

int *p1, *p2;  // defines 2 pointers to int
int *p1, p2;   // p1 is a pointer-to-int, whereas p2 is an int

Tacking the * to the type makes the latter definition very confusing:

int* p1, p2;  // p1 is a pointer-to-int, whereas p2 is an int

As a consequence, defining variables with different indirection levels on the same line is also strongly discouraged.

I think the reason int *p2 = &i; is confusing is the combined effect of the simultaneous declaration and instantiation, and the spacing. I'll explain.

Typically, for a pointer-to-integer p2 and an integer i , writing " *p2 " dereferences p2 and gives the int living at the address &i .

So the code " int *p2 = &i; " makes it look like an int is being set equal to a memory address.

Indeed, the code

int i = 1;
int *p2;
*p2 = &i

is wrong, because in the last line, *p2 is an int since it is p2 dereferenced, and &i is a pointer.

Why int *p2 = &i; is NOT doing the same thing as the last line of the flawed code above:

The code int *p2 = &i; is different from the 3 lines of code above because it is a declaration. When you declare a pointer variable, you put the type, (eg int , long , char , etc.), and the name of your variable (like normal) - and you also put an asterisk * in between these two pieces (see @chqrlie answer above with regard to the many spacing options for this - takehome is best-practice is to adhere the * to the variable name). In a declaration, the * is NOT dereferencing the pointer. Rather, it is telling the compiler that the variable myPointer will be a pointer to memory holding data of the declared type (the int , long , char , etc. from before). So, in the bit of code " int *p2 = &i; ", where the pointer is being declared and instantiated at the same time, the * does not render an int on the left-hand side. For declarations, while it is safer (as @chqrlie points out) to put the * next to the variable name, this does not unwrap the pointer even if the pointer is instantiated in the declaration. For declarations, think of the * as being attached to the type (rather than to the variable name, where for good reasons it is likely to be). I like to declare pointers with the * right next to the pointer name, but just understand that when instantiating a pointer in the declaration, a perhaps clearer way for a new learner to imagine the line would be int* p2 = &1 :

int* (type pionter-to-int) p2 (name of pointer) = &i (equals the pointer that gives the address of integer i ) ;

Thank you to everyone who answered and commented, and good luck to everyone who may have come here trying to figure out something about pointers.

Pointers are abstractions of memory addresses, with some associated type semantics.

p2 has type int * , or "pointer to int ". It stores the location of an integer object (in this case, the location of the object i ). The type of the expression *p2 is int :

 p2 == &i;  // both expressions have type int * and evaluate to an address value
*p2 ==  i;  // both expressions have type int and evaluate to an integer value

Pointers are as big as they need to be to store an address value, however that address value is represented for the given platform (whether that's a single integer value, or a pair of values representing a page number and offset, or some other format). Note that different pointer types may be different sizes, although on modern desktop architectures they are all the same size (32 or 64 bit).

The type of the pointer matters for pointer arithmetic. Given a pointer p , the expression p + 1 yields the address of the next object of the pointed-to type. If the pointed-to type is 1 byte wide (such as char ) and its current address is 0x8000, then p + 1 yields the address of the next byte, or 0x8001. If the type is 4 bytes wide (such as a long ) and its current address is 0x8000, then p + 1 yields the address of the fourth next byte, or 0x8004.

A pointer is its own type. If it were used with a different syntax it could be written like this:

Pointer x = new Pointer(int, address);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM