I'm trying to do the following
int a[8]={1,2,3,4,5,6,7,8};
printf("%f\n", *(float *)a);
printf("%f\n", *((float *)a+1));
printf("%f\n", *((float *)a+2));
printf("%f\n", *((float *)a+3));
printf("%f\n", *((float *)a+4));
printf("%f\n", *((float *)a+5));
printf("%f\n", *((float *)a+6));
printf("%f\n", *((float *)a+7));
I get
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
The reason why I'm trying to print the elements in this way is because, I want to cast the int pointer to the array to the float pointer and pass it as a parameter for another function which only takes float *.
It seems that this does not work well. Can someone explain why this is not working?
int *ptr;
function((float *)ptr);
If I do this the function does not read the values the pointer is pointing to properly.. just returning 0.0000.
This is not correct. int and float are not guaranteed to have the same alignment.
Remember: Casting a value and casting a pointer are different scenarios. Casting a pointer changes the way to refer to the type value, which can almost certainly result in a mis-alignment in most of the cases.
As per C11 standard document, chapter §6.3.2.3
A pointer to an object type may be converted to a pointer to a different object type. If the resulting pointer is not correctly aligned68) for the referenced type, the behavior is undefined.
In your case, a work-around may be
printf("%f\n", (float)*a); //cast the value, not the pointer
You cannot cast a pointer to int to a pointer to float, and expect to get your value converted to the corresponding number in floating point representation. Casting a single value works, but casting by changing a pointer type does not alter the representation.
If you need an array of floats, declare an array of floats, and cast one element at a time:
float b[8];
for (int i = 0 ; i != 8 ; i++) {
b[i] = a[i];
}
func_expects_float(b, 8);
Casting an int pointer to a float doesn't convert the integer to a floating point number. Casting just tells the machine to use the contents of the memory location pointed to by the pointer as floating point value instead of an integer value. But it doesn't change the value from integer representation to floating point representation.
you might try:
printf( "%f\n", 1.0f * a[0]);
printf( "%f\n", 1.0f * a[1]);
....
==or==
printf( "%f\n", *(a+0) * 1.0f );
printf( "%f\n", *(a+1) * 1.0f );
....
Related
Why doesn't typecasting work here..?
#include<stdio.h>
int main(){
int x = 5;
float y = 7.0;
float *p = &y;
int *q = &x;
printf("p is %d\nq is %d\np - q is %d", p, q, (p - q));
return 0;
}
I am getting this error invalid operands of types 'float*' and 'int*' to binary 'operator-'; what does it mean?
The error means that the compiler is unable to deduce the common type of two operands one of which has the type float * and other int *. There is no implicit conversion between these types.
But in any case the program has undefined behavior because at least you may not subtract two pointers that do not point to elements of the same array or to a memory after the last element of the same array.
From the C Standard (6.5.6 Additive operators)
9 When two pointers are subtracted, both shall point to elements of
the same array object, or one past the last element of the array
object; the result is the difference of the subscripts of the two
array elements.
And using incorrect conversion specifiers (as for example %d with a pointer) for supplied arguments in the function printf also invokes undefined behavior.
From the C Standard (7.21.6.1 The fprintf function)
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.
I suppose you want to subtract the actual values your pointers are pointing to.
C converts int to float implicitly when you are operating on float and int.
Also, you program has some problems as
Not using %f type specifier to print float pointer
Not using the * operator to access pointer values.
Here is your program, working:
#include <stdio.h>
int main()
{
int x = 5;
float y = 7.0;
float *p = &y;
int *q = &x;
printf("p is %f\nq is %d\np - q is %f", *p, *q, (*p - *q));
return 0;
}
With the outputs:
p is 7.000000
q is 5
p - q is 2.000000
You can't subtract pointers like that and get a meaningful result in standard C.
Per 6.5.6 Additive operators, paragraph 9 of the C11 standard:
When two pointers are subtracted, both shall point to elements of the same array object, or one past the last element of the array object; the result is the difference of the subscripts of the two array elements.
In this case, a single int or float variable is considered to be an array of size 1.
So given
int x = 5;
float y = 7.0;
float *p = &y;
int *q = &x;
trying to compute the value p - q results in undefined behavior.
Per J.2 Undefined behavior:
The behavior is undefined in the following circumstances:
...
Pointers that do not point into, or just beyond, the same array object are subtracted
However, code like this likely won't cause problems as it's merely subtracting two integer values (although I haven't checked thoroughly), but the result doesn't have to be meaningful:
int x = 5;
float y = 7.0;
float *p = &y;
int *q = &x;
intptr_t diff = ( intptr_t ) p - ( intptr_t ) q;
Edit: As has been pointed out in the comments, subtracting two void* pointers is not proper standard C. If you want to subtract two pointers to find the distance between them the correct approach is to cast them to an appropriately sized integer, and then do integer arithmetic.
E.g.:
printf("p is %p\nq is %p\np - q is %ld\n", p, q, ((intptr_t)p - (intptr_t)q));
Original answer:
It means that the minus operator is not defined for mixed types of pointers. If you want to subtract those two pointers, for example to find the amount of space between them, the better option would be to cast them both to void* pointers.
Also, you should print pointer values with the %p specifier instead of %d.
E.g.:
printf("p is %p\nq is %p\np - q is %ld\n", p, q, ((void*)p - (void*)q));
I came up on this question:
I have the following instruction
float *f = (float*) malloc(5*sizeof(float));
and a consequence of this is that
&f is of type float**
I don't understand why it's like this.
The type of f is float*, i.e., a pointer to float. So &f is the address of f, so its type is address to pointer of float, aka pointer to pointer of float, meaning float**.
I have the following instruction
That thingies are called "statements".
float *f = (float*) malloc(5*sizeof(float));
Don't cast the result of malloc:
float *f = malloc(5 * sizeof(float));
Even better, determine the size by the pointer you allocate memory for:
float *f = malloc(5 * sizeof(*f)); // 5 times sizeof the type, f points to
That way you are safe even if the type of f would change. No chance of forgetting to change the type after sizeof.
Now f points to a region of memory large enough to hold five consecutive floats;
f is just a variable like all others. Lets take the address of some less scary variable first:
int i;
int *ptr = &i; // &i yields the address of the variable i.
// The type of i is (int),
// so a pointer to it is of type (pointer to (int)) -> int*
now f:
float *f = malloc(5 * sizeof(*f)); // or, instead of the result of malloc() simply
// the address of some automatic float variable
float **ptr = &f; // &f yields the address of the variable f.
// The type of f is (pointer to float) -> float*,
// so a pointer to it is of type (pointer to (pointer to float) -> float**
Let's start with a simpler example:
int a = 42;
in this example a in a variable that contains the value 42.
&a is the address of that variable. It can be stored in a pointer:
int *b = &a;
A variable of type int * is a pointer to a variable of type int.
Back to your question:
In your case, the type of f isn't int but float*. As a consequence, the type of &f is float**.
In general, the type of an expression like
&something
is pointer to the type of something. Since the type of f is *float, the type of &f must be pointer to *float, which is written as **float.
Conversely, if the type of something is *sometype (i.e. pointer to sometype), the type of *something is sometype. So if you have
float **f;
then the type of *f is *float, and the type of **f is float.
A pointer to an object holds the address of an object. In your case, f is a pointer to float, which is to say that the value of f is the address of a floating-point number (assuming the pointer isn't invalid).
By extension, then &f is the address of f, which is to say that it's the address of a pointer to float, or if you prefer, it's the address of the address of a float, which is the same as saying it is a pointer to a pointer to a floating-point number.
I am trying to understand the pointer concepts in-depth.
In the following code,
#include <stdio.h>
int main()
{
int i = 10;
int *iptr = &i;
printf("(float)* : %f\n", (float)*iptr);
printf("(float*) : %f\n", (float*)iptr);
printf("*(float*) : %f\n", *(float*)iptr);
return 0;
}
output:
(float)* : 10.000000
(float*) : 10.000000
*(float*) : 0.000000
I also got a warning for the type-cast (float*).
I find it difficult to even analyse the difference. If anyone can help me to analyse what is the exact usage of all three, it would be helpful.
The difference is
You are dereferencing the int and casting it to float in
printf("(float)* : %f\n", (float)*iptr);
which is fine.
You are casting the int pointer to a float pointer, and printing the float pointer with the "%f" specifier is undefined behavior, the correct specifier for printing pointers is "%p", so
printf("(float*) : %f\n", (float*)iptr);
is wrong, it should be
printf("(float*) : %p\n", (void *) iptr);
casting to float * here is not meaningful, because the void * address is the same as the float * address and also the int * address, the difference would be when you do pointer arithmetic.
You are casting the int pointer to a float and dereferencing the resulting float pointer, although it will violate strict aliasing rules in
printf("(float*) : %f\n", *(float*)iptr);
which is also undefined behavior
The first one is correct.
i is an int variable, and iptr a pointer to that int.
(float)*iptr: *iptr dereferences iptr, which returns an int. Then that int is converted to a temporary float containing the same value. And that float is used by printf.
*(float*)iptr: Attempts to cast a pointer-to-int into a pointer-to-float. This is invalid, and should produce a compiler warning or error. It creates a pointer with the same address, but with the type saying that it points to a float value.
The * operator then dereferences it, so the int is read as if it were a float. So the resulting float would be invalid, and it could result in a segfault because floats are longer than ints, so it reads more memory than there is allocated for the int.
(float*)iptr: Same problem, but it doesn't dereference the (invalid) pointer, and passes a pointer-to-float into printf, instead of a float. But printf expects a float. Some compilers should also produce a warning/error here because the format string indicates what value types are expected.
If the format specifier indicates %p, it expects a pointer (void*, float*, or any other). It will then print out the address, and not the value it points to. This can be useful in debugging for example.
We have some float x and we convert it into i, but could anyone please explain what does do in depth first &, then cast and finally *?
int i = *(int*)&x;
&x
Gets a pointer to x
(int*)&x
Casts that pointer to an int*, i.e. a pointer to an int
*(int*)&x
Dereferences the resulting pointer, reading the memory of variable x as if it were an int.
Without knowing the type x is, it's hard to tell what the code's purpose. Most likely, if x is a float, it's being used to get the binary representation of the float (which is impossible to do by just casting to an int, because it does a float to int conversion)
&x: Get a pointer to x
(int*): Cast that pointer to a pointer to an int - this does not actually cast x
*: Retrieve the value the pointer points to
Since a pointer cast doesn't actually perform type conversion, this line of code has the effect of reading the internal bits used to store the float x, and storing those bits int the integer i. Basically, this is a reinterpret_cast. (reinterpret_cast is a C++ feature, but it does exactly the same thing as this C syntax.)
"&" means getting the reference of a variable. So &x gets the reference to a float and has type float*.
(int*) is a cast. Therefore you are casting from float* to int*.
The last "*" is for dereferencing the int*, that is, getting the value of the int*, which is an int.
Lets break it down
&x; //this gets you the address of x
(int *)&x; //this cast the address to be pointing at an integer value
//(before it was pointing at a float value)
*(int *)&x; // now the last * dereferences that value
assuming in your system, long is 8bytes and int is 4bytes. so you get only 4 bytes of the 8 bytes of x. As int is usually 4 bytes and long 8 bytes. Now which of the 4 bytes you get (the first 4 or the last 4) depends on the endianness of your system..
For more info on endianness, read this http://en.wikipedia.org/wiki/Endianness
I would like to know if there is a difference between:
Casting a primitive variable to another primitive type
Dereferencing a cast of a primitive variable's address to a pointer of another primitive type
I would also like to know if there is a good reason to ever use (2) over (1). I have seen (2) in legacy code which is why I was wondering. From the context, I couldn't understand why (2) was being favored over (1). And from the following test I wrote, I have concluded that at least the behavior of an upcast is the same in either case:
/* compile with gcc -lm */
#include <stdio.h>
#include <math.h>
int main(void)
{
unsigned max_unsigned = pow(2, 8 * sizeof(unsigned)) - 1;
printf("VALUES:\n");
printf("%u\n", max_unsigned + 1);
printf("%lu\n", (unsigned long)max_unsigned + 1); /* case 1 */
printf("%lu\n", *((unsigned long *)&max_unsigned) + 1); /* case 2 */
printf("SIZES:\n");
printf("%d\n", sizeof(max_unsigned));
printf("%d\n", sizeof((unsigned long)max_unsigned)); /* case 1 */
printf("%d\n", sizeof(*((unsigned long *)&max_unsigned))); /* case 2 */
return 0;
}
Output:
VALUES:
0
4294967296
4294967296
SIZES:
4
8
8
From my perspective, there should be no differences between (1) and (2), but I wanted to consult the SO experts for a sanity check.
The first cast is legal; the second cast may not be legal.
The first cast tells the compiler to use the knowledge of the type of the variable to make a conversion to the desired type; the compiler does it, provided that a proper conversion is defined in the language standard.
The second cast tells the compiler to forget its knowledge of the variable's type, and re-interpret its internal representation as that of a different type *. This has limited applicability: as long as the binary representation matches that of the type pointed by the target pointer, this conversion will work. However, this is not equivalent to the first cast, because in this situation value conversion never takes place.
Switching the type of the variable being cast to something with a different representation, say, a float, illustrates this point well: the first conversion produces a correct result, while the second conversion produces garbage:
float test = 123456.0f;
printf("VALUES:\n");
printf("%f\n", test + 1);
printf("%lu\n", (unsigned long)test + 1);
printf("%lu\n", *((unsigned long *)&test) + 1); // Undefined behavior
This prints
123457.000000
123457
1206984705
(demo)
* This is valid only when one of the types is a character type and the pointer alignment is valid, type conversion is trivial (i.e. when there is no conversion), when you change qualifiers or signedness, or when you cast to/from a struct/union with the first member being a valid conversion source/target. Otherwise, this leads to undefined behavior. See C 2011 (N1570), 6.5 7, for complete description. Thanks, Eric Postpischil, for pointing out the situations when the second conversion is defined.
Let's look at two simple examples, with int and float on modern hardware (no funny business).
float x = 1.0f;
printf("(int) x = %d\n", (int) x);
printf("*(int *) &x = %d\n", *(int *) &x);
Output, maybe... (your results may differ)
(int) x = 1
*(int *) &x = 1065353216
What happens with (int) x is you convert the value, 1.0f, to an integer.
What happens with *(int *) &x is you pretend that the value was already an integer. It was NOT an integer.
The floating point representation of 1.0 happens to be the following (in binary):
00111111 100000000 00000000 0000000
Which is the same representation as the integer 1065353216.
This:
(type)variable
takes the value of variable and converts it to type type. This conversion does not necessarily just copy the bits of the representation; it follows the language rules for conversions. Depending on the source and target types, the result may have the same mathematical value as variable, but it may be represented completely differently.
This:
*((type *)&variable)
does something called aliasing, sometimes informally called type-punning. It takes the chunk of memory occupied by variable and treats it as if it were an object of type type. It can yield odd results, or even crash your program, if the source and target types have different representations (say, an integer and a floating-point type), or even if they're of different sizes. For example, if variable is a 16-bit integer (say, it's of type short), and type is a 32-bit integer type, then at best you'll get a 32-bit result containing 16 bits of garbage -- whereas a simple value conversion would have given you a mathematically correct result.
The pointer cast form can also give you alignment problems. If variable is byte-aligned and type requires 2-byte or 4-byte alignment, for example, you can get undefined behavior, which could result either in a garbage result or a program crash. Or, worse yet, it might appear to work (which means you have a hidden bug that may show up later and be very difficult to track down).
You can examine the representation of an object by taking its address and converting it to unsigned char*; the language specifically permits treating any object as an array of character type.
But if a simple value conversion does the job, then that's what you should use.
If variable and type are both arithmetic, the cast is probably unnecessary; you can assign an expression of any arithmetic type to an object of any arithmetic type, and the conversion will be done implicitly.
Here's an example where the two forms have very different behavior:
#include <stdio.h>
int main(void) {
float x = 123.456;
printf("d = %g, sizeof (float) = %zu, sizeof (unsigned int) = %zu\n",
x, sizeof (float), sizeof (unsigned int));
printf("Value conversion: %u\n", (unsigned int)x);
printf("Aliasing : %u\n", *(unsigned int*)&x);
}
The output on my system (it may be different on yours) is:
d = 123.456, sizeof (float) = 4, sizeof (unsigned int) = 4
Value conversion: 123
Aliasing : 1123477881
What's the difference between “(type)variable” and “*((type *)&variable)”, if any?
The second expression may lead to alignment and aliasing issues.
The first form is the natural way to convert a value to another type. But assuming there is no violation of alignment or aliasing, in some cases the second expression has an advantage over the first form. *((type *)&variable) will yield a lvalue whereas (type)variable will not yield a lvalue (the result of a cast is never a lvalue).
This allows you do things like:
(*((type *)& expr)))++
See for example this option from Apple gcc manual which performs a similar trick:
-fnon-lvalue-assign (APPLE ONLY): Whenever an lvalue cast or an lvalue conditional expression is encountered, the compiler will issue a deprecation warning
and then rewrite the expression as follows:
(type)expr ---becomes---> *(type *)&expr
cond ? expr1 : expr2 ---becomes---> *(cond ? &expr1 : &expr2)
Casting the pointer makes a difference when working on a structure:
struct foo {
int a;
};
void foo()
{
int c;
((struct foo)(c)).a = 23; // bad
(*(struct foo *)(&c)).a = 42; // ok
}
First one ((type)variable is simple casting a variable to desired type and second one (*(type*)&variable) is derefencing a pointer after being casted by the desired pointer type.
The difference is that in the second case you may have undefined behavior. The reason being that unsinged is the same as unsigned int and an unsigned long may be larger than the the unsigned int, and when casting to a pointer which you dereference you read also the uninitialized part of the unsigned long.
The first case simply converts the unsigned int to an unsigned long with extends the unsigned int as needed.