5

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.

J0e3gan
  • 8,740
  • 10
  • 53
  • 80
Min Fu
  • 789
  • 1
  • 6
  • 16
  • 1
    There is no such provision in the language standard that the pointer is always convertible to integer. It is just a coincidence, like int is for some reason long now. – Alexander V Nov 29 '14 at 07:06
  • this code should produce a warning about using a pointer as an integer without a cast. – user3629249 Nov 29 '14 at 07:08
  • if you had placed this code in a file and compiled it (with warnings enabled) the compiler would have flagged the code as incorrect. Then there would have been no need to ask the question – user3629249 Nov 29 '14 at 07:10
  • Nothing is *always* safe; of course a pointer isn't *just* an `integer` but it is always representable as an `integer` (it might be an `int` or a `long` or even a 30-bit value but you could declare that is an `integer`). – Elliott Frisch Nov 29 '14 at 07:12
  • In non-linear addressing architectures (such as x86 real mode), a pointer might not even be a single number. For example (again) in x86 real mode, a so-called "FAR" pointer is the composition of a segment address and an offset within the segment. – Euro Micelli Nov 29 '14 at 08:26
  • I don't understand. If pointer is not an integer(long or short or binary or whatever), what else could it be? Thanks. – posixKing Oct 14 '16 at 18:22

5 Answers5

7

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.

Yu Hao
  • 119,891
  • 44
  • 235
  • 294
  • They are normally the same as `ptrdiff_t` (signed) and `size_t` (unsigned), correct? – technosaurus Nov 29 '14 at 07:33
  • 1
    @technosaurus [Not really](http://stackoverflow.com/q/1464174/1009479). Note also that `ptrdiff_t` and `size_t` are not optional. – Yu Hao Nov 29 '14 at 07:37
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 of p are copied into b
  • 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.

barak manos
  • 29,648
  • 10
  • 62
  • 114
0

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.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
0

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.

Anbu.Sankar
  • 1,326
  • 8
  • 15
-1

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.

BufBills
  • 8,005
  • 12
  • 48
  • 90