-
pointer struggles ???
Pointers continually elude me.....See below two 'supposedly' equivalent examples:
int A;
int *pA;
pA = &A;
int A;
int *pA = (int *)A;
I am doing an online course and the instructor uses the second method. I understand the first method but every time I see the '*' I think of dereferencing so the typecasting (int *)A does not seem equiv. to &A. Can someone explain in a very basic way?
Thanks
-
They are not equivalent, so you might want to change instructor if that's what the instructor told you.
To elaborate: the second method treats the int value as the address of an int. So pA does not point to A, unlike the first method. There's no dereferencing involved; rather the type of the object named A has been reinterpreted to be an int* instead of an int.
-
I think that there is something missing there, because they are in no way the same
-
This is an embedded block of code looking at a register on an STM32 processor. The following compiles without error:
Code:
#include <stdint.h>
#define RCC_BASE_ADDR 0x40023800U
int main(void)
{
uint32_t *p;
p = (uint32_t *)RCC_BASE_ADDR;
/* Loop forever */
for(;;);
}
The following compiles with error:
Code:
#include <stdint.h>
#define RCC_BASE_ADDR 0x40023800U
int main(void)
{
uint32_t *p;
p = (uint32_t *)(&RCC_BASE_ADDR);
/* Loop forever */
for(;;);
}
What I am failing to understand is I thought that a pointer in this case p should be pointing to an address (aka use of &). Why is the second block of code not correct? Or for that matter why does the first block of code work without the &?
Thank you
-
RCC_BASE_ADDR is a macro, so after macro replacement, it is as if you had written:
Code:
p = (uint32_t *)(&0x40023800U);
-
It's already been "pointed" out that the two examples are not equivalent. But you can initialize a pointer variable using a typecast integer value.
That second example only makes sense if the integer variable A contains a valid memory address of an int object. Since you haven't given A a value to convert, though, the result of (int*)A is "undefined behavior". It will probably compile without even a warning, though. Beware.
C allows a typecast to convert pointers to and from integer values. This isn't used much in applications that run under a modern OS, since the addresses of data objects aren't known at compile time. Also, except for the case of an integer 0 value (which converts to a null pointer), integer-to-pointer conversions are highly non-portable.
You'll see it in embedded code, in OS kernel code, device drivers, etc. to get a pointer, say, to memory-mapped I/O ports or data stored in some sort of read-only memory. You'll also see it in assembly-level debuggers, converting hexadecimal input to a pointer into the program being debugged.
So, converting integers to pointers isn't unheard of, but it's not common either. I would not teach it as a first method, and I wouldn't teach it at all without stressing, LOUDLY, that A must be initialized to a valid memory address.
-
ridderunnersjw, think of pointers as types that hold an address and addresses are unsigned integers (linke indices of an array). In C there are a difference in declaring an object and using it. If you do:
You are asking the compiler to reserve space for a pointer identified as pa and what goes inside pa is an unsigned integer which will be interpreted as an address when you use the indirection operator * in an expression using this object, as in:
When declaring the object the * isn't the indirection operator, it only tells the compiler that pa is a pointer to an specified type (int, in this case).
The & operator takes the address of other objects, as in:
Code:
int a;
int *pa;
pa = &a; // assign the "address of" a to pa
Since pa is an unsigned integer, but not necessarily of unsigned int type -- it depends of the address size -- it is risky to assume any integer type will fit in the pointer object as an address. The standard library provides some typedefs to allow you to assign integers at pointer types directly: size_t, for example, has the same size as a pointer (not necessarily). And, in stdint.h, there is a uintptr_t type.
Notice your previous example is wrong. It's not possible to take an address from a literal:
Code:
p=(uint32_t *) &RCC_BASE_ADDR;
This should be:
Code:
p=(uint32_t *)RCC_BASE_ADDR;
-
Thank you all for the help!