Pantelis Sopasakis
Pantelis Sopasakis

Reputation: 1902

void* weirdness in C

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

Answers (4)

Theodoros Chatzigiannakis
Theodoros Chatzigiannakis

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

Keith Thompson
Keith Thompson

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

Craig
Craig

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

sr01853
sr01853

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

Related Questions