how to convert pointer to integer in c? - c

the easiest way to fix this, please show your work
attempt
int x = (int)p
error
warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]

The best way to use an integer type to hold a pointer value is to use uintptr_t type.
From the C11, chapter 7.20.1.4,
The following type designates an unsigned integer type with the property that any valid pointer to void can be converted to this type, then converted back to pointer to void, and the result will compare equal to the original pointer:
uintptr_t
If you want a signed integer type instead, use intptr_t.

Related

What is the appropriate arithmetic type for a pointer?

In my code I have two char pointer, one to a string and the other as an error indicator for strtoumax() and strtod(). I am currently using the type size_t (aka unsigned long) to calculate the difference between them. Is there any type designed to specifically match pointer type size on every machine? Or do I have to check it myself with macros?
For pointer difference use ptrdiff_t. If you're just trying to store a pointer as an integer, use uintptr_t (or intptr_t).
In my code I have two char pointer, one to a string and the other as
an error indicator for strtoumax() and strtod(). I am currently using
the type size_t (aka unsigned long) to calculate the difference
between them.
Don't do that. If you want a pointer difference then compute a pointer difference:
#include <stdint.h>
// ...
ptrdiff_t difference = p2 - p1;
And note ptrdiff_t, which is the type of the result of a pointer difference.
If you want a difference in bytes instead of in units the size of the pointed-to type (including if the pointed-to type is incomplete, such as void) then first convert to pointers to char:
ptrdiff_t difference_in_bytes = (char *) p2 - (char *) p1;
(char is the smallest addressible unit of storage, but technically, it might be larger than 8 bits on some C implementations. CHAR_BIT will help you figure that out if you're concerned about such cases.)
Do not compute a pointer difference by converting to integer and performing integer arithmetic, because although the behavior of that is defined (+/- signed integer overflow), the meaning of the result is not.
Is there any type designed to specifically match pointer
type size on every machine? Or do I have to check it myself with
macros?
Yes. In stdint.h there are definitions of uintptr_t and intptr_t, which can support round-trip pointer to integer to pointer conversions without data loss. But C does not define the meaning of the value resulting from converting a pointer to an integer, so these are best used as opaque types.
To store pointers as integers you can use intptr_t and uintptr_t declared in the header <stdint.h>.
From the C Standard (7.20.1.4 Integer types capable of holding object pointers)
1 The following type designates a signed integer type with the
property that any valid pointer to void can be converted to this type,
then converted back to pointer to void, and the result will compare
equal to the original pointer:
intptr_t
The following type designates an unsigned integer type with the
property that any valid pointer to void can be converted to this type,
then converted back to pointer to void, and the result will compare
equal to the original pointer:
uintptr_t
These types are optional.
To store difference between two pointers you can use ptrdiff_t declared in the header <stddef.h>.
Pay attention to that you may calculate difference between two pointers if they both point to elements of the same array or one past the last element. Otherwise you will get undefined behavior.

Casting malloc to a primitive type

How is this allowed in C?
int p= (int) malloc (sizeof(int));
I only get a warning when I compile in gcc.
warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
A void pointer cannot be casted to a primitive type right?
*((int*)(x))//is allowed - assume x is of type void*
But how is direct cast to primitive also allowed?
This is not forbidden, but implementation defined behaviour. Quoting C11, chapter ยง6.3.2.3
Any pointer type may be converted to an integer type. Except as previously specified, the
result is implementation-defined. If the result cannot be represented in the integer type,
the behavior is undefined. The result need not be in the range of values of any integer
type.
That is why compiler emits the warning.
That said, quoting chapter 7.20.1.4, Integer types capable of holding object pointers, we have intptr_t and uintptr_t.
The following type designates a signed integer type with the property that any valid
pointer to void can be converted to this type, then converted back to pointer to void,
and the result will compare equal to the original pointer:
intptr_t
The following type designates an unsigned integer type with the property that any valid
pointer to void can be converted to this type, then converted back to pointer to void,
and the result will compare equal to the original pointer:
uintptr_t
Having said that, just for sake of completeness's sake, let me add that, there is fair amount of reasons on why not to cast the return value of malloc() and family in C..

Difference between address of a variable and integer

Whats the difference between integer and the address returned by & ?
Therefore, why should I type-cast integer to an integer pointer when assigning it to an integer pointer?
Integer and pointer to integer are different types.
Integer variable holds integer value.
Pointer variable holds address value.
Given your example:
int value = 5;
int address = &value;
value is variable of type int.
&value returns address of type int*
address = &value tries to assign int* to int.
While integers can be converted to pointers and back, it doesn't mean that addresses are necessarily integer values.
Just like you can assign double to int, you can assign int * to int. But it's not necessarily what you want, and that's why compiler warns about it.
In fact, unless you are working very close to hardware (writing driver for example), it's very unlikely you need to do conversions between integers and pointers.
Correct way to do this, without needing any casts:
int * pointer = &value;
Whats the difference between integer and the address returned by & ?
I think this question has already been answered in the comments. The difference is the type of those variables. Basically int = Integer type and *int = Pointer type.
Furthermore: Conversion from pointer to int can result in undefined behavior.
Therefore, why should I type-cast integer to an integer pointer when
assigning it to an integer pointer?
Because the standard says:
C99 Section 6.5.4 and 6.5.16.1:
Conversions that involve pointers, other than where permitted by the
constraints of 6.5.16.1, shall be specified by means of an explicit
cast.
And C++ Section 5.4:
Any type conversion not mentioned below and not explicitly defined by
the user (12.3) is ill-formed.

Casting a pointer to an int

I am writing my own functions for malloc and free in C for an assignment. I need to take advantage of the C sbrk() wrapper function. From what I understand sbrk() increments the program's data space by the number of bytes passed as an argument and points to the location of the program break.
If I have the following code snippet:
#define BLOCK_SIZE 20
int x;
x = (int)sbrk(BLOCK_SIZE + 4);
I get the compiler error warning: cast from pointer to integer of different size. Why is this and is there anyway I can cast the address pointed to by sbrk() to an int?
I get the compiler error warning: cast from pointer to integer of different size.
Why is this
Because pointer and int may have different length, for example, on 64-bit system, sizeof(void *) (i.e. length of pointer) usually is 8, but sizeof(int) usually is 4. In this case, if you cast a pointer to an int and cast it back, you will get a invalid pointer instead of the original pointer.
and is there anyway I can cast the address pointed to by sbrk() to an int?
If you really need to cast a pointer to an integer, you should cast it to an intptr_t or uintptr_t, from <stdint.h>.
From <stdint.h>(P):
Integer types capable of holding object pointers
The following type designates a signed integer type with the property that any valid pointer to void can be converted to this type, then converted back to a pointer to void, and the result will compare equal to the original pointer: intptr_t
The following type designates an unsigned integer type with the property that any valid pointer to void can be converted to this type, then converted back to a pointer to void, and the result will compare equal to the original pointer: uintptr_t
On XSI-conformant systems, the intptr_t and uintptr_t types are required; otherwise, they are optional.

What is intptr_t,is it a type for integer or pointer?

It's defined in /usr/include/stdint.h:
typedef long int intptr_t;
is it supposed to be a type for integer or pointer?
It is a signed integer type that is big enough to hold a pointer.
It is a signed integer type that guaranteed to can hold a void* type.
And why there is also [u]intptr_t? Because:
Any valid pointer to void can be converted to intptr_t or uintptr_t
and back with no change in value. The C Standard
guarantees that a pointer to void may be converted to or from a
pointer to any object type and back again and that the result must
compare equal to the original pointer. Consequently, converting
directly from a char * pointer to a uintptr_t is allowed on implementations that support the uintptr_t.

Resources