If I know the address of an data object, could I store the address as an integer and operate the integer as a pointer?
For example,
void main(){
long a = 101010;
long *p = &a;
long b = p;
printf("%lld\n", *(long*)b);
}
Is it always safe?
Comments: long b = p;
produces a warning:
Initialization makes integer from pointer without a cast
However, the program prints 101010
.
'Integer' in a programming language can be defined as any data type representing a mathematical subset. On the other hand, 'pointer' can be defined as a type that refers or points to another value which is stored in some part of the memory of the computer. Integers exist mainly as binary value in a computer system.
Pointer is a data type and the purest form of it in C is void *. A void * can pass the memory address around which is what a pointer does but it cannot be dereferenced. Dereferencing means to get at the data contained at the memory location the pointer is pointing at.
A pointer variable (or pointer in short) is basically the same as the other variables, which can store a piece of data. Unlike normal variable which stores a value (such as an int, a double, a char), a pointer stores a memory address. Pointers must be declared before they can be used, just like a normal variable.
Every pointer is of some specific type. There's a special generic pointer type void* that can point to any object type, but you have to convert a void* to some specific pointer type before you can dereference it.
It's not guaranteed by the standard that such cast would always work.
To store a pointer in an integral type, use intptr_t
(or its unsigned cousin uintptr_t
). It's guaranteed to convert void *
pointers to such types and convert back, resulting the same value.
Note that these types are optional.
sizeof(long)
is typically defined by the compiler (subjected to the underlying HW architecture).
sizeof(long*)
is subjected to the size of the virtual memory address space on your platform.
For example, with the Visual Studio compiler for 64-bit operating system and x64-based processor:
sizeof(long) == 4
sizeof(long*) == 8
Therefore:
long b = p
, only the 4 least significant bytes of p
are copied into b
*(long*)b
, you are potentially attempting to access an invalid memory addressIn this example, if the 4 most significant bytes of p
are zero, then "no harm is done". But since it is not guaranteed to be the case, when sizeof(long) != sizeof(long*)
this code is generally unsafe.
In addition to that, even if sizeof(long) == sizeof(long*)
, you should still refrain from using this type of conversions (pointer-to-integer), in order to keep your code portable to other platforms.
UPDATE
Please note that printf("%lld\n", *(long*)b)
is also unsafe.
You should basically use "%ld"
for long
values and "%lld"
for long long
values.
If sizeof(long) < sizeof(long long)
, then it may lead to a memory access violation during runtime.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With