-1

Is it valid to cast int to int*? If yes, what does it mean? And if no, what is the problem?

int a=10;
printf("%d", (int *)a);

It's just a not &a. It prints 10 in devc++. Doesn't (int *)a mean a pointer to address 10 and not a pointer to some address which stores the value 10?

Ahh! I am still confused. I have one more situation which i cant figure out.

int b=516;
printf("\n %d",((char *)b));

It prints 516. Shouldn't it print 4? Please explain.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
CodeTry
  • 312
  • 1
  • 19
  • You can. It doesn't mean it'll be meaningful. When dereferenced, it'll jump to the memory address that the bits in the int represent. – Ben Nov 11 '14 at 19:43
  • 1
    You're doing two things with undefined behaviour - you are casting an `int` to an `int *`, and then you are printing an `int *` value using `%d`. On your compiler and machine, the effect of both these errors is to cancel each other out and print 10. – Greg Hewgill Nov 11 '14 at 19:44
  • 1
    You're using "%d", which means "I promise the argument is an int". Try "%p". (Then you'll be down to one instance of undefined behaviour instead of two.) Alternatively use `cout << reinterpret_cast(a)`. – Alan Stokes Nov 11 '14 at 19:46
  • @GregHewgill Only of pointer and int have the same size I would assume. – Oncaphillis Nov 11 '14 at 19:46
  • @Oncaphillis: Yes, on some compiler/machine combinations, the above code will not output 10. – Greg Hewgill Nov 11 '14 at 19:47
  • @Oncaphillis now, as long as int is smaller than the pointer size it should be able to be cast. You see this most commonly in embedded type systems where you may want to do things like say, parsing hardware-mapped ram. – IdeaHat Nov 11 '14 at 19:48
  • If you must cast a pointer to an integer, the standard compliant way would be to use `intptr_t` or `uintptr_t`. – R Sahu Nov 11 '14 at 19:48
  • @RSahu actually he tries exactly opposite - int to pointer. – Slava Nov 11 '14 at 19:55
  • @Slava, if an `intptr_t` was properly initialized, it can be cast back to a valid pointer. – R Sahu Nov 11 '14 at 19:57
  • @RSahu good to know, but that not what OP is asking about. – Slava Nov 11 '14 at 19:58
  • @Slava, true. It's not clear what the OP's intent is. – R Sahu Nov 11 '14 at 20:05

3 Answers3

5

According to C Standard (6.3.2.3 Pointers)

5 An integer may be converted to any pointer type. Except as previously specified, the result is implementation-defined, might not be correctly aligned, might not point to an entity of the referenced type, and might be a trap representation.67)

In your code snippet

int a=10;
printf("%d", (int *)a);

pointer (int *)a might not be correctly aligned for example when sizeof( int * ) is equal to either 4 or 8. Also take into account that this call of printf

printf("%d", (int *)a);

has undefined behaviour,

From the C Standard (7.21.6.1 The fprintf function - the same is valid for printf)

9 If a conversion specification is invalid, the behavior is undefined.275) If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined.

As for this code snippet

int b=516;
printf("\n %d",((char *)b)); 

then the compiler pushes on the stack value 516 as an address but inside function printf and due to format specifier %d the function considers this value again as an integer object and outputs it accordingly.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • 1
    Does `(int *)a` also break [strict aliasing](http://stackoverflow.com/questions/98650/what-is-the-strict-aliasing-rule) rule, provoking another UB? I always have some trouble identyfing it. – Grzegorz Szpetkowski Nov 11 '14 at 20:52
  • 1
    @Grzegorz Szpetkowski There is no deregerencing. Simply the pointer is not correctly alligned and can be greater in size then the size of int. – Vlad from Moscow Nov 11 '14 at 20:58
  • Thanx Vlad. Could you please explain the second part of the question also? – CodeTry Nov 14 '14 at 13:23
1

The cast of int to int* is undefined. This means anything could happen. What is likely to happen is that it will point to the block of memory indexed as 10, whatever that means. Some compilers could be implemented so that int and int* have different sizes, which would cause different issues.

Know, if you lucked out, and (int *)a points to address 10, and you want to see what's there, you can dereference it with

printf("%d", *(int *)a);

Warning: This will probably/possibly/maybe cause a segmentation fault similar to forgetting to malloc memory.

TL;DR: Don't do it.

Degustaf
  • 2,655
  • 2
  • 16
  • 27
  • `printf("%d", &(int *)a);` -- Try compiling that. `(int *)a` is not an lvalue, so it's illegal to apply the unary `&` operator to it. Did you mean `printf("%d", *(int*)a);`? – Keith Thompson Nov 11 '14 at 20:18
1

Yes you can cast an integer to a pointer, but the semantics are context dependent. The bit pattern of the integer will be interpreted as an address, which may or may not be valid.

Your example makes little sense, while (int*)a is an address equal to 0xA, the %d format specifier causes printf() to interpret the value as an integer in any case - which is why it prints 10, but as an address, it will still have value 10 - even if that address is not valid.

Consider:

int a = 10 ;
intptr_t p = (int)&a ; // cast a valid pointer to integer 
                       // large enough to hold an address
int ap = (int*)a ;     // a reinterpreted as a pointer

printf( "%d\n", a ) ;           // Print a
printf( "%p\n", &a ) ;          // Print address of a
printf( "%d (0x%X)\n", p, p ) ; // Print p - an integer equal to &a
printf( "%p\n", ap ) ;          // Print ap - a interpreted as a pointer
Clifford
  • 88,407
  • 13
  • 85
  • 165
  • 1
    You posted the same answer twice. I suggest deleting this one (you have an upvote on the other). (I haven't checked whether they're identical.) -- Aaaand, you just deleted the one that had an upvote. – Keith Thompson Nov 11 '14 at 20:19
  • I didn't do that - SO or my Chromebook browser did that all on its own! This version is the most recent and most correct. I am not sufficiently bothered to chase the upvote. – Clifford Nov 11 '14 at 20:20
  • In case you missed the update to my previous comment, you might want to undelete the other answer and delete this one, so you don't lose the upvote. – Keith Thompson Nov 11 '14 at 20:21