问题
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
.
回答1:
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.
回答2:
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:
- With
long b = p
, only the 4 least significant bytes ofp
are copied intob
- With
*(long*)b
, you are potentially attempting to access an invalid memory address
In 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.
回答3:
Even p
value and b
value are same, only p
can access a
i.e can to point a
, b
can not point to a
. Because p
is declared as pointer. b
is declared as variable.
You cant access a
through b
. Then how is your question suitable. In b
, address of a
is treated as only value
not aaddress
, because of b
is variable not a pointer..
Even it prints 101010
, this program is not a generic.
回答4:
To be on safe side, we should consider it's not safe.
Size of a pointer on a n
bit system is n
bits. For example, size of a pointer should be 8 byte on any 64-bit architecture / compiler. That's guranteed.
However, there is no such gurantee for data types. Its heavily compiler dependent. In your case, both just happens to have the same size, that's why it works.
EDIT:
For the warning
Initialization makes integer from pointer without a cast
Your compiler is very much right for producing the warning. Please check the data type. An int *
variable is not equal to an int
variable. In your case, it works just because there lengths are same in your particular case / implementation.
回答5:
A pointer is a variable whose value is the address of another variable. Like any variable or constant, you must declare a pointer before you can work with it. The general form of a pointer variable declaration is:
type *var-name;
The actual data type of the value of all pointers, whether integer, float, character, or otherwise, is the same, a long hexadecimal number that represents a memory address. The only difference between pointers of different data types is the data type of the variable or constant that the pointer points to.
Pointers generally have a fixed size, for ex. on a 32-bit executable they're usually 32-bit. There are some exceptions, like on old 16-bit windows when you had to distinguish between 32-bit pointers and 16-bit... It's usually pretty safe to assume they're going to be uniform within a given executable on modern desktop OS's.
来源:https://stackoverflow.com/questions/27199805/is-pointer-just-an-integer