Reputation: 1902
I am studying functions that accept arguments of arbitrary datatypes using void pointers. Such a function is the following:
void funct(void *a) {
float *p = a;
printf("number = %f\n",*p);
}
Here is a successful invocation to funct
:
float x = 1.0f;
funct(&x);
x
is declared to be a float and then its pointer, namely &x
(which is of type float*
) is passed to funct
; quite straightforward!
There is however yet another way to declare a variable in C and get its pointer. This is:
float *p;
*p = 1.0f;
But then the call funct(&x);
returns a Segmentation fault: 11
! How is that possible?
Additionally, assume that I want to create a method that accepts a "number" (i.e. float, integer, double, float or anything else (e.g. even u_short)) and adds 1 to it. What would the most versatile implementation possibly be? Should I consider the following prototype:
void add_one(void* x);
?
Upvotes: 0
Views: 145
Reputation: 29233
First off, I must make something clear. float *p
and float* p
are equivalent statements. If you're a beginner in C, I recommend that you write the latter instead of the former, because it makes clearer what the type is and what the variable is - it will save you a lot of confusion in the future. With that in mind, please remember that in the following block p
, not *p
, is the variable.
float* p;
*p = 1.0f;
The first line allocates a float*
on the stack. As it happens with all variables allocated on the stack, its initial value is undefined (most probably garbage). This is not exclusive to pointers: even if you allocate an int
and you don't initialize it, it will have an undefined value.
The same happens with p
, so you should think of p
as containing random data initially. If p
contains random data and it's a pointer, it means that it's pointing to a random address. Attempting (in the second line) to write the value 1.0f
(or anything else) to that random address will almost always cause a segmentation fault, because a random address at any given time has little chance of belonging to your program.
Upvotes: 1
Reputation: 263647
float *p = 1;
is invalid; your compiler should at the very least have issued a warning. It attempts to initialize a pointer variable (of type float*
) with an integer expression (type int
, value 1
).
There is no implicit conversion in standard C from int
to float*
.
If your compiler warned you about that line, pay attention to the warning. If it didn't, play with your compiler options until it does, or get a better (more modern?) compiler.
As for a function that takes a pointer to an variable and adds 1 to it regardless of its type, there's really no way to do that in C. Conceivably you could write a function that takes a void*
pointer and a second argument that indicates its type, then use a switch
statement in the function to decide what conversions to perform. But it's a whole lot easier just to write
x ++;
In response to your updated question:
float *p;
That's valid; it defined p
as a pointer to float
.
*p = 1.0f;
The compiler probably won't complain about that, but since you haven't assigned a value to p
, it probably doesn't point to a valid object. *p = 1.0f;
has undefined behavior. If you're lucky, your program will crash; if you're unlucky, it will appear to work.
Upvotes: 3
Reputation: 3307
In float *p
, p is a pointer to a float. You can't say *p = 1.0
without first making the pointer p point to something. For example,
float *p = new float;
*p = 1.0f;
That might work.
Upvotes: 1
Reputation: 6121
By declaring
float *p;
p is supposed to be pointer holding the address of a valid float variable. Here you are just assinging a number to p.
*p = 1.0f;
This would lead to undefined behaviour. since p does not hold any valid address and you are simply trying to dereference it.
Upvotes: 1