Pointer subtraction confusion - c

When subtracting two pointers from each other the difference represents the number of elements between them (when pointing to int).
Why is the difference zero when pointing to type double?
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[])
{
double data[10] = {1,2,3,4,5,6,7,8,9};
double *iptr1;
double *iptr2;
double val;
iptr1 = &data[0];
iptr2 = &data[9];
val = iptr2 - iptr1;
printf("Distance between the two addresses = %d\n", val);
return 0;
}

You are printing a double value with %d, which expects an integer. Change the type of val to int and everything will work as expected.
Note that, as suggested in the comments below, C defines a type for pointer differences, ptrdiff_t. This is guaranteed to always hold a value arising from a pointer difference, regardless of how far the actual pointers are. Although, if you are absolutely sure that the difference will fit an int, as in your question, that type should be fine as well. But double makes no sense at all, pointer differences cannot be fractional values.

Double is not the correct type for pointer differences. Use ptrdiff_t, as defined in stddef.h instead.
See here for the Data Types
Instead of
printf("Distance between the two addresses = %d\n", val);
use then also
ptrdiff_t val = iptr2 - iptr1;
printf("Distance between the two addresses = %td\n", val);

Related

How to access data of another variable by pointing to a slack-byte in a structure?

#include <stdio.h>
#include <stdlib.h>
struct someStruct {
int ivar;
char cvar;
float fvar;
};
main(argc,argv)
const char** argv;
{
struct someStruct someObj;
someObj.ivar = 1;
someObj.fvar = 2.3;
someObj.cvar = 'r';
printf("%u\n",&someObj.fvar);
printf("%u\n",(&someObj.cvar + 4));
printf("%f\n",*((&someObj.cvar) + 4));
printf("%f\n",someObj.fvar);
}
This is a program I wrote which tries to access the address of fvar by adding 4 to the address of char.
I know the concept of slack-byte. I tried to access that memory, and lo! it printed the address correctly.
printf("%u\n",&someObj.fvar);
printf("%u\n",(&someObj.cvar + 4));
Both print the same address.
Then I tried to access fvar in the following way:
printf("%f\n",*((&someObj.cvar) + 4));
printf("%f\n",someObj.fvar);
and
0.000000
2.300000
were my results.
Then I realised that char* and float* are interpreted differently.
So, I tried all kinds of typecasting from char* to float* to float and also from char to float* to float and that too at all possible points like for e.g., typecasting the returned address to float,using 4.0 instead of 4 (which I realised wasn't supposed to work... and it didn't),etc.
It somehow just doesn't print 2.300000 and keeps printing 0.000000
Where am I missing the concept?
Note that I have a 64-bit MinGW and adds slack-byte (I know some don't) which I've already verified by:
printf("%u",sizeof(someObj.ivar));
printf("%u",sizeof(someObj.fvar));
printf("%u",sizeof(someObj.cvar));
printf("%u",sizeof(someObj));
which yields 4, 4, 1 and 12 ....(sizeof(char) + 3) respectively.
P.S. I know this is a horrible idea, but this is how I usually learn concepts XD
Assuming that the following is true:
&someObj.cvar + 4 == &someObj.fvar
you can cast the pointer value to a proper type:
printf("%f\n", *(float*)((&someObj.cvar) + 4));
(&someObj.cvar) is a pointer to char, so *(&someObj.cvar) is a char. The %f printf specifier expects a double or a float, passing a char is invalid. Note: float when passed in variadic functions as one of the arguments in ellipsis parameter is implicitly converted to double, see ex. cppreference implicit conversions. You have to pass a double or a float to %f, not a char.
Notes:
main(argc,argv)
const char** argv;
{
Don't use implicit int declaration and old, deprecated, obsolete style of function declaration. Use the normal style:
int main(int argc, char **argv) {
printf("%u\n",&someObj.fvar); is undefined behavior. The %u expects unsigned char, not float *. You can print a void* pointer using %p specifier: printf("%p\n", (void*)&someObj.fvar); or cast it to unsinged int: printf("%u\n", (unsigned int)(uintptr_t)(void*)&someObj.fvar);
C has an macro offsetof declared in stddef.h to access the number of "slack-bytes" (I like the name "padding bytes" better). You can: printf("%f", *(float*)((char*)&someObj + offsetof(struct someStruct, fvar)));

C Why can't a void pointer store a float value?

I'm trying to return a float value but when I print it out, I get 0.0.
float floating = 4.5;
void* function(){
void* test = &floating;
return test;
}
int _tmain(int argc, _TCHAR* argv[]){
printf("%f\n", test());
return 0;
}
Any ideas on why it's not printing out 4.5? Sorry if this is a noob question, I'm still fairly new to this.
Assuming your function() is actually spelled as test(), %f expects a float value. You're supplying a void *. It's wrong and undefined behaviour.
Solution: void being an incomplete type, you cannot dereference a void pointer directly. You need to cast the pointer to the required type before dereferencing. For example,
printf("%f\n", *( (float *) test() ) );
Trying to provide a bit more details about that:
First, from how you phrased your question, you should understand that pointers don't store values, they store addresses of objects. void is no type at all, and a void * pointer might store the address of anything (as long as it's data, but I don't want to overcomplicate my answer right here).
That's probably where you came from in the first place. But then you made two mistakes:
The %f format specifier of printf() doesn't expect a pointer, it expects a value. There's one operation called dereferencing a pointer that fetches the value the pointer points to. In c expressions, you have the dereferencing operator written as an asterisk (*) in front of your value to do that.
So how can you read a value without knowing the type? You can't! That's why dereferencing a void * pointer is illegal. Means, even if you didn't forget the asterisk and wrote for example printf("%f\n", *(test()));, the code would be wrong (and this time, your compiler would catch the error).
That being said, void * pointers in c are meant as a generic pointer and are therefore implicitly convertible to and from any other data pointer type (note this is different in c++). So one way to write your program correctly would be:
int _tmain(int argc, _TCHAR* argv[]){
float *f = test();
printf("%f\n", *f);
return 0;
}
edit: From the fact that void * is implicitly convertible to/from other data pointer types follows your test() could be as simple as that:
void *test()
{
return &floating;
}
edit2: As you're new to pointers, adding an advice not directly related to your question: In a variable declaration in c, the asterisk binds to the identifier (variable name), not to the type. This means you read int * foo; not as "foo is a variable of type pointer to int" but as "foo is a pointer variable of type int". This has a serious implication when writing e.g. int * foo, bar; -- foo will be a pointer, bar a normal variable. Therefore the advice is: make it explicit by writing e.g. void *test instead of void* test.
Try
printf("%f\n", *( (float*)function() ));
What printf sees is a parameter value. That value isn't a float, but is a pointer to a float. You would need to cast it back to a float* and dereference it.
I have test in my IDE. The function() is correct, what you need to modify is printf(). My answer:
#include <stdio.h>
float floating = 4.5;
void* test(){
void* test = &floating;
return test;
}
int main()
{
printf("%f\n", *(float *)test()); //modify here
return 0;
}
I hope this can help you.
The %f conversion specifier expects it's corresponding argument to have type float; you're passing it a void *, hence the garbage output.
Change that to
printf( "%f\n", * ((float *) test()) );
You have to convert the void * returned from test to a float *, then dereference the result to get the actual float value. The cast is necessary, since you cannot directly deference a void *.
You dont print 4.5, because you are returning a pointer over the variable "floating" not the variable itself.
You have to change your code to :
int _tmain(int argc, _TCHAR* argv[]){
printf("%f\n", (*(float*)function()));
return 0;
}

floating point constant in C, bit representation

It is possible to access to the bit representation of a floating point constant in C;
For example i'd like to assign
uint64_t x = //bit representation of 5.74;
which is represented by
0x40b7ae14
Do you think it is possible?
One way of achieving this is to use a union:
union {
double fltValue;
uint64_t uintValue;
} conversion;
conversion.fltValue = 5.74;
printf("%#llx\n", conversion.uintValue);
Updated with %#x thanks to Aracthor for mentioning it. And %#llx thanks to EOF.
For a working example (with float instead of double) see:
https://ideone.com/p4rH5l
It is possible, but is not portable because you cannot be sure of how a floating point value is represented : C standard does not define it.
You could simply use casting of pointers :
float x = 5.74;
void *pt = &x
uint64_t *ip = pt;
uint64_t i = *ip;
This is formal undefined behaviour because you are casting a pointer to a different type, and you should not do it because you add endian problems to the floating point representation.
The correct way would be :
float x = 5.74;
void *pt = &x
unsigned char *ip = pt;
ip now point to a unsigned char[] of size sizeof(float) containing the binary representation of a float. And no undefined behaviour was invoked because casting a pointer to a void *or a char * is always allowed.
#include <stdint.h>
#include <stdio.h>
int main(void) {
double x = 5.74;
uint64_t y = *((uint64_t*)&x);
printf("0x%016llx", y); /* 0x4016f5c28f5c28f6 */
}
If you are asking for the binary representation of float, then take an integer pointer..assign the address of the float variable to the integer pointer and by derefenencing the value of int pointer, get its binary form..and in the middle if you somehow want to avoid the warning generated by unusual typecasting then you can always use void*

How do I correctly use a void pointer in C?

Can someone explain why I do not get the value of the variable, but its memory instead?
I need to use void* to point to "unsigned short" values.
As I understand void pointers, their size is unknown and their type is unknown.
Once initialize them however, they are known, right?
Why does my printf statement print the wrong value?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void func(int a, void *res){
res = &a;
printf("res = %d\n", *(int*)res);
int b;
b = * (int *) res;
printf("b =%d\n", b);
}
int main (int argc, char* argv[])
{
//trial 1
int a = 30;
void *res = (int *)a;
func(a, res);
printf("result = %d\n", (int)res);
//trial 2
unsigned short i = 90;
res = &i;
func(i, res);
printf("result = %d\n", (unsigned short)res);
return 0;
}
The output I get:
res = 30
b =30
result = 30
res = 90
b =90
result = 44974
One thing to keep in mind: C does not guarantee that int will be big enough to hold a pointer (including void*). That cast is not a portable thing/good idea. Use %p to printf a pointer.
Likewise, you're doing a "bad cast" here: void* res = (int*) a is telling the compiler: "I am sure that the value of a is a valid int*, so you should treat it as such." Unless you actually know for a fact that there is an int stored at memory address 30, this is wrong.
Fortunately, you immediately overwrite res with the address of the other a. (You have two vars named a and two named res, the ones in main and the ones in func. The ones in func are copies of the value of the one in main, when you call it there.) Generally speaking, overwriting the value of a parameter to a function is "bad form," but it is technically legal. Personally, I recommend declaring all of your functions' parameters as const 99% of the time (e.g. void func (const int a, const void* res))
Then, you cast res to an unsigned short. I don't think anybody's still running on a 16-bit address-space CPU (well, your Apple II, maybe), so that will definitely corrupt the value of res by truncating it.
In general, in C, typecasts are dangerous. You're overruling the compiler's type system, and saying: "look here, Mr Compiler, I'm the programmer, and I know better than you what I have here. So, you just be quiet and make this happen." Casting from a pointer to a non-pointer type is almost universally wrong. Casting between pointer types is more often wrong than not.
I'd suggest checking out some of the "Related" links down this page to find a good overview of how C types an pointers work, in general. Sometimes it takes reading over a few to really get a grasp on how this stuff goes together.
(unsigned short)res
is a cast on a pointer, res is a memory address, by casting it to an unsigned short, you get the address value as an unsigned short instead of hexadecimal value, to be sure that you are going to get a correct value you can print
*(unsigned short*)res
The first cast (unsigned short*)res makes a cast on void* pointer to a pointer on unsigned short. You can then extract the value inside the memory address res is pointing to by dereferencing it using the *
If you have a void pointer ptr that you know points to an int, in order to access to that int write:
int i = *(int*)ptr;
That is, first cast it to a pointer-to-int with cast operator (int*) and then dereference it to get the pointed-to value.
You are casting the pointer directly to a value type, and although the compiler will happily do it, that's not probably what you want.
A void pointer is used in C as a kind of generic pointer. A void pointer variable can be used to contain the address of any variable type. The problem with a void pointer is once you have assigned an address to the pointer, the information about the type of variable is no longer available for the compiler to check against.
In general, void pointers should be avoided since the type of the variable whose address is in the void pointer is no longer available to the compiler. On the other hand, there are cases where a void pointer is very handy. However it is up to the programmer to know the type of variable whose address is in the void pointer variable and to use it properly.
Much of older C source has C style casts between type pointers and void pointers. This is not necessary with modern compilers and should be avoided.
The size of a void pointer variable is known. What is not known is the size of the variable whose pointer is in the void pointer variable. For instance here are some source examples.
// create several different kinds of variables
int iValue;
char aszString[6];
float fValue;
int *pIvalue = &iValue;
void *pVoid = 0;
int iSize = sizeof(*pIvalue); // get size of what int pointer points to, an int
int vSize = sizeof(*pVoid); // compile error, size of what void pointer points to is unknown
int vSizeVar = sizeof(pVoid); // compiles fine size of void pointer is known
pVoid = &iValue; // put the address of iValue into the void pointer variable
pVoid = &aszString[0]; // put the address of char string into the void pointer variable
pVoid = &fValue; // put the address of float into the void pointer variable
pIvalue = &fValue; // compiler error, address of float into int pointer not allowed
One way that void pointers have been used is by having several different types of structs which are provided as an argument for a function, typically some kind of a dispatching function. Since the interface for the function allows for different pointer types, a void pointer must be used in the argument list. Then the type of variable pointed to is determined by either an additional argument or inspecting the variable pointed to. An example of that type of use of a function would be something like the following. In this case we include an indicator as to the type of the struct in the first member of the various permutations of the struct. As long as all structs that are used with this function have as their first member an int indicating the type of struct, this will work.
struct struct_1 {
int iClass; // struct type indicator. must always be first member of struct
int iValue;
};
struct struct_2 {
int iClass; // struct type indicator. must always be first member of struct
float fValue;
};
void func2 (void *pStruct)
{
struct struct_1 *pStruct_1 = pStruct;
struct struct_2 *pStruct_2 = pStruct;
switch (pStruct_1->iClass) // this works because a struct is a kind of template or pattern for a memory location
{
case 1:
// do things with pStruct_1
break;
case 2:
// do things with pStruct_2
break;
default:
break;
}
}
void xfunc (void)
{
struct struct_1 myStruct_1 = {1, 37};
struct struct_2 myStruct_2 = {2, 755.37f};
func2 (&myStruct_1);
func2 (&myStruct_2);
}
Something like the above has a number of software design problems with the coupling and cohesion so unless you have good reasons for using this approach, it is better to rethink your design. However the C programming language allows you to do this.
There are some cases where the void pointer is necessary. For instance the malloc() function which allocates memory returns a void pointer containing the address of the area that has been allocated (or NULL if the allocation failed). The void pointer in this case allows for a single malloc() function that can return the address of memory for any type of variable. The following shows use of malloc() with various variable types.
void yfunc (void)
{
int *pIvalue = malloc(sizeof(int));
char *paszStr = malloc(sizeof(char)*32);
struct struct_1 *pStruct_1 = malloc (sizeof(*pStruct_1));
struct struct_2 *pStruct_2Array = malloc (sizeof(*pStruct_2Array)*21);
pStruct_1->iClass = 1; pStruct_1->iValue = 23;
func2(pStruct_1); // pStruct_1 is already a pointer so address of is not used
{
int i;
for (i = 0; i < 21; i++) {
pStruct_2Array[i].iClass = 2;
pStruct_2Array[i].fValue = 123.33f;
func2 (&pStruct_2Array[i]); // address of particular array element. could also use func2 (pStruct_2Array + i)
}
}
free(pStruct_1);
free(pStruct_2Array); // free the entire array which was allocated with single malloc()
free(pIvalue);
free(paszStr);
}
If what you want to do is pass the variable a by name and use it, try something like:
void func(int* src)
{
printf( "%d\n", *src );
}
If you get a void* from a library function, and you know its actual type, you should immediately store it in a variable of the right type:
int *ap = calloc( 1, sizeof(int) );
There are a few situations in which you must receive a parameter by reference as a void* and then cast it. The one I’ve run into most often in the real world is a thread procedure. So, you might write something like:
#include <stddef.h>
#include <stdio.h>
#include <pthread.h>
void* thread_proc( void* arg )
{
const int a = *(int*)arg;
/** Alternatively, with no explicit casts:
* const int* const p = arg;
* const int a = *p;
*/
printf( "Daughter thread: %d\n", a );
fflush(stdout); /* If more than one thread outputs, should be atomic. */
return NULL;
}
int main(void)
{
int a = 1;
const pthread_t tid = pthread_create( thread_proc, &a );
pthread_join(tid, NULL);
return EXIT_SUCCESS;
}
If you want to live dangerously, you could pass a uintptr_t value cast to void* and cast it back, but beware of trap representations.
printf("result = %d\n", (int)res); is printing the value of res (a pointer) as a number.
Remember that a pointer is an address in memory, so this will print some random looking 32bit number.
If you wanted to print the value stored at that address then you need (int)*res - although the (int) is unnecessary.
edit: if you want to print the value (ie address) of a pointer then you should use %p it's essentially the same but formats it better and understands if the size of an int and a poitner are different on your platform
void *res = (int *)a;
a is a int but not a ptr, maybe it should be:
void *res = &a;
The size of a void pointer is known; it's the size of an address, so the same size as any other pointer. You are freely converting between an integer and a pointer, and that's dangerous. If you mean to take the address of the variable a, you need to convert its address to a void * with (void *)&a.

How to cast a void* to int in 64-bit platforms, using C?

I am a linguist in charge of a C program, so please excuse me if the answer is obvious. I have the following code:
typedef struct array_s {
(...)
void **value;
} array_t;
typedef array_t *array_pt;
array_pt array_new (int size) {
(...)
array->value = (void **)malloc(size*sizeof(void *));
}
void* array_get (array_pt arr, int i) {
return arr->value[i];
}
int main () {
int a = 1234;
int *ptr = &a;
array_pt array = array_new(1);
array_add(array, ptr);
printf("%i\n", (int)array_get(array, 0));
}
It is supposed to provide me with a multi-purpose array (for storing int and char*, if I understood I can only use void), and I guess there are no problems of allocating/freeing. However, I cannot get to cast it into anything useful (i.e., get back the "original" int/char*), and for what I understood it could be because I am in a 64-bit system and the size of a pointer to void is different from the size of a pointer to int/char* (the program is supposed to be used in both 64 and 32 bit systems). I tried using intptr_t and other alternatives, to no luck.
How can I be sure that the code will accept any data type and work on both 32 and 64 bit systems? Thank you.
EDIT:
Sorry for not adding array_add, here it is:
unsigned int array_add (array_pt array, void *ptr) {
(...) // get the next index
// allocate if needed
array->value = (void **)realloc(array->value, array->size*sizeof(void *));
array->value[index] = p;
}
You need to dereference your pointer:
int* temp = array_get(array, 0);
printf("%i\n", *temp);
However, I strongly recommend avoiding this type of approach. You're basically giving away the small amount of help the compiler in C will normally provide - purposefully trying to make non-typesafe arrays.
You need to decide what is it you are trying to do in this case.
(1) If you want to use your void * array to store int values (actual int forcefully converted to void *), then you should add these int values to the array as follows
int a = 1234;
array_pt array = array_new(1);
array_add(array, (void *) a);
and then get them back from array as follows
int a = (int) array_get(array, 0);
printf ("%d\n", a);
or simply
printf ("%d\n", (int) array_get(array, 0)));
That last part is exactly what you did, but you got the first part wrong.
This is a cast-based approach, which is ugly in many ways, but it has certain practical value, and it will work assuming void * is large enough to hold an int. This is the approach that might depend on the properties of 32- and 64-bit systems.
(2) If you want to use your void * array to store int * values (pointers to int), then you should add these int values to the array as follows
int a = 1234;
array_pt array = array_new(1);
array_add(array, &a);
and then get them back from array as follows
int *pa = array_get(array, 0);
printf ("%d\n", *pa);
or simply
printf ("%d\n", *(int *) array_get(array, 0));
This approach is perfectly safe from any portability problems. It has no 32- or 64-bit issues. A void * pointer is guaranteed to safely hold a int * pointer or any other data pointer.
If that was your intent, then you got the first part right and the last part wrong.
Either this or that. You code appears to be a strange mix of the two, which is why it doesn't work, and which is why it is impossible to figure out from your original message which approach you were trying to use.
intmax_t should be an integer type that is 32 bits on 32bits compilers and 64bits on 64bit compilers. You could use %j in your printf statement to print intmax_t. The size of pointers on one system is always the same - independently of them pointing to int, char or void.
printf("%j\n", (intmax_t)array_get(array, 0));

Resources