GCC gives me folowing warning:
note: expected 'const void **' but argument is of type 'const struct auth **
Is there any case, where it could cause problems?
Bigger snippet is
struct auth *current;
gl_list_iterator_next(&it, ¤t, NULL);
Function just stores in current some void * pointer.
The error message is clear enough: you are passing a struct auth ** where a void ** was accepted. There is no implicit conversion between these types as a void* may not have the same size and alignment as other pointer types.
The solution is to use an intermediate void*:
void *current_void;
struct auth *current;
gl_list_iterator_next(&it, ¤t_void, NULL);
current = current_void;
EDIT: to address the comments below, here's an example of why this is necessary. Suppose you're on a platform where sizeof(struct auth*) == sizeof(short) == 2, while sizeof(void*) == sizeof(long) == 4; that's allowed by the C standard and platforms with varying pointer sizes actually exist. Then the OP's code would be similar to doing
short current;
long *p = (long *)(¤t); // cast added, similar to casting to void**
// now call a function that does writes to *p, as in
*p = 0xDEADBEEF; // undefined behavior!
However, this program too can be made to work by introducing an intermediate long (although the result may only be meaningful when the long's value is small enough to store in a short).
Hm... I think constructs like const void * doesn't makes much sense.
Because if user wants to access data under void * he needs casting from void, and this action bypasses compiler type checks and consequently - constantness.
Consider this example:
#include <stdio.h>
#include <stdlib.h>
int main () {
int i = 6;
int * pi = &i;
const void * pcv = pi;
const int * pci = pi;
// casting avoids type checker, so constantness is irrelevant here
*(int *)pcv = 7;
// here we don't need casting, and thus compiler is able to guard read-only data
*pci = 7;
return 0;
}
So conclusion is that we need either void pointer Or to ensure constantness of data, but not both.
Related
Following code works fine, however I was wondering if this is valid use of rule that void* is compatible with any other pointer
#include <stdio.h>
typedef struct {
int foo;
} SomeStruct_t;
typedef void(*SomeFunction_t)(void* ptr);
void bar(SomeStruct_t* str) {
printf("%d\n", str->foo);
}
void teddy(void* anyPtr) {
SomeStruct_t* str = (SomeStruct_t*)anyPtr;
printf("%d\n", str->foo);
}
int main()
{
SomeFunction_t functPtr = (SomeFunction_t)bar;
SomeStruct_t data = {.foo = 33};
functPtr(&data);
functPtr = teddy;
functPtr(&data);
return 0;
}
Question is, should I use bar or teddy variant? I prefer bar but I'm not sure if for some corner cases this might lead to hard to detect problem.
This is not valid:
SomeFunction_t functPtr = (SomeFunction_t)bar;
Because you're casing a function pointer of type void (*)(SomeStruct_t*) to type void (*)(void*) and subsequently calling it though the casted type. The function pointer types are not compatible because the parameters are not compatible. This triggers undefined behavior.
While a SomeStruct_t * can be converted to a void *, that conversion can't happen because the casted function pointer prevents it. There's no guarantee that SomeStruct_t * and void * have the same representation.
Using the function teddy which matches the function pointer type is safe. Also, you don't need to cast the parameter to SomeStruct_t * inside the function because conversions to/from void * don't require one in most cases.
Is it ever common to do something like the following:
void *x = (void *) "one";
void *y = (void *) 2;
void *z = (void *) NULL;
Instead of:
char * x = "one";
int y = 2;
My reason for asking this is the ability to call a function that can accept multiple types. For example, a concat of various elements like is available in javascript. It seems like in a way using (void *) is just a simple way to mean "any type".
No, because you can't dereference a void pointer: you have to know what type is being stored, rendering the idea useless.
What you might be looking for is a variant type.
enum type {
CHAR, INT, DOUBLE, STR
};
typedef struct {
union {
char c;
int i;
double d;
char *str;
};
enum type t;
} variant;
void displayGenericObjec(variant v)
{
switch (v.t) {
case CHAR:
putchar(v.c);
break;
case INT:
printf("%d", v.i);
break;
case DOUBLE:
printf("%f", v.d);
break;
case STR:
printf("%s", v.str);
break;
}
}
variant x;
x.t = INT;
x.i = 42;
displayGenericObject(x);
This isn't a very practical solution, but it works for trivial code that only needs a few types.
Usually, it is not a good idea to write functions that take any argument. As noted in the comments, you lose on the compiler provided type-checking.
However, there are some cases where you might want to consider this using 'void *', which are (usually) considered acceptable are: (1) varargs functions and (2) callback. Important to emphasize that it is better to consider alternative implementation, if possible.
varargs functions are functions like 'printf', 'scanf', etc, where the function can accept variable number of arguments, potentially of different types, and will usually use clues (or convention) from the first arguments to properly decode the remaining arguments.
Callback are other example, where the code will sometimes have to specify a function that will be called on event. Many frameworks will require the callback to match a predefined "typedef", where the code will later cast the arguments into the actual type. For example, the 'qsort' prototype require a 'compar' function, which is generically defined to take 'void *', where the actual function will cast the parameters to the actual type.
void qsort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
On historical note, the initial versions of "C" (sometimes call "K&R C") did allow functions to be defined without formal parameter list. Practical experience has proven this to be risky, non-productive. In those days, you could write function in header files like:
/* in file.h */
int foo() ;
/* in file.c */
int foo(a)
int a ;
{
}
/* in prog.c */
{
a(5,4,"x") ;
}
Say I have a const pointer to an array as a function argument like so:
int* test(const int* inputArg)
And within the function I want to assign inputArg as one of the members of a struct, like so:
typedef struct {
int * intArray;
} structSample;
structSample abc;
abc.intArray = inputArg;
How should I cast inputArg to achieve this? Right now if I compile it, error will be shown saying that
error: assigning to 'int *' from 'const int *'
Thank you
First of all, you do not have
a const pointer to an array
What you have is a pointer to constant integer. If you really wanted a constant pointer to integer as an argument, you would have to have the prototype declared as follows:
int* test(int* const inputArg)
Unless, of course, something else was in mind.
Update from comment:
So basically if you want to have a pointer to constant int stored in your function as a struct member, you can declare it just like that:
struct SampleStruct
{
const int* a;
/* whatever follows */
};
int* test(const int* inputArg)
{
struct SampleStruct ss;
ss.a = inputArg;
/* other code */
}
You must be aware, that in doing so, you must be const correct. That means, since both (argument and field) are pointers to constant integers, you must not change the values at that address(es).
abc.intArray = (int*)inputArg;
This is the C-style cast. On a side not the compiler didn't allow the const conversion by default because it's dangerous to do so. You are removing the const at your own risk.
For eg if your test is called like
const int max = 100;
//centuries later
test(&max);
and you do go ahead with the cast:
abc.intArray = (int*)inputArg;
// after another century later
*(abc.intArray) = 10; // kaboom. Undefined behavior. Debugging is a nightmare at this point
The best solution here would be changing the function to
int* test(int* inputArg)
{
/* do whatever you wish to do with inputArg itself
* why bother to create a structure and all?
* The whole purpose you wanted the const int* inputArg
* was to prevent any accidental change of data pointed to by it
* Wasn't it?
*/
}
It looks like that you are using Werror flag (this shouldn't be an error but a warning)
There is a way to lie to the compiler (using unions) without warnings:
#include <stdio.h>
int *test(const int *inputArg)
{
union {int *nonconstant; const int *constant;} fake = {.constant = inputArg};
int *p = fake.nonconstant;
return p;
}
int main(void)
{
const int x = 500;
int *p = test(&x);
*p = 100; /* Boom */
return 0;
}
As pointed out by others, don't do it :)
I have two structures:
typedef struct abc {
unsigned int pref;
unsigned int port;
char *aRecordIp;
int index;
int count;
}abc_t;
typedef struct xyz {
abc_t *ab;
int index;
int count;
}xyz_t;
and I would like to achieve the following
int Lookup (char *lookup,void *handle) {
*handle = (xyz_t *)malloc(sizeof(xyz_t *));
handle->ab = (abc_t *) malloc(sizeof(abc_t *));
//
}
I am trying to typecast void pointer to xyz_t basically.
Is this correct?
You are doing it wrong on multiple counts:
You're trying to set a variable handle->ab, but handle is a void *, not a structure type pointer.
You need to show your call, but there's likely to be problems — why do you think a void * argument is a good idea?
You want to allocate structures, so the sizeof() operands should be xyz_t and not xyz_t *; repeat for abc_t.
You should probably use:
int Lookup(const char *lookup, xyz_t **handle)
{
...
*handle = (xyz_t *)malloc(sizeof(xyz_t));
(*handle)->ab = (abc_t *)malloc(sizeof(abc_t));
...
}
Don't forget to check the result of malloc().
There are those who will castigate you for using casts on malloc(). I won't. When I learned C (a long time ago, years before there was a C standard), on a machine where the int * value for an address was not the same bit pattern as the char * address for the same memory location, where malloc() had to be declared char *malloc() or all hell broke loose, the casts were necessary. But — and this is the major issue that people are concerned about — it is crucial that you compile with compiler options such that if you invoke a function without a prototype in scope, you will get a compilation error, or a warning that you will pay attention to. The concern is that if you do not have a declaration for malloc() in scope, you will get incorrect results from using the cast which the compiler would diagnose if you don't.
On the whole, though, I think you should separate your lookup code from your 'create xyz_t' code — your function is doing two jobs and it complicates the interface to your function.
xyz_t *Create_xyz(void);
int Lookup(const char *lookup, const xyz_t *handle);
While casting of a void* to any pointer type is correct, it is not necessary in C, and it is not recommended for malloc (e.g. see Do I cast the result of malloc? ).
Also, you should specify sizeof(xyz_t), not sieof(xyz_t*), otherwise you allocate memory enough only for pointer, not for the whole structure.
And of course you should assign a pointer to handle, not to *handle. And handle should be of proper pointer type (xyz_t*).
Oh, and if the question is about casting handle to xyz_t*, then you can do it like ((xyz_t*)handle)->ab.
I'd recommend reading a book before playing with pointers like that.
I believe you want handle to hold a valid address of a xyz_t struct after the function call. Then you need to change the function signature and contents like so:
int Lookup (char *lookup, xyz_t **handle) { // double indirection here
*handle = (xyz_t *)malloc(sizeof(xyz_t));
(*handle)->ab = (abc_t *) malloc(sizeof(abc_t));
}
And call it like this:
xyz_t *myhandle;
char lookup;
Lookup(&lookup, &mynandle);
// now you can use it
myhandle->index ...
You will need to free the memory as well...
free(myhandle->ab);
free(myhandle);
If you want to pass void *, here is the solution
int Lookup (char *lookup, void *handle) {
handle = malloc(sizeof(xyz_t));
((xyz_t *)handle)->ab = (abc_t *) malloc(sizeof(abc_t));
//
}
Even though it is possible to write generic code in C using void pointer(generic pointer), I find that it is quite difficult to debug the code since void pointer can take any pointer type without warning from compiler.
(e.g function foo() take void pointer which is supposed to be pointer to struct, but compiler won't complain if char array is passed.)
What kind of approach/strategy do you all use when using void pointer in C?
The solution is not to use void* unless you really, really have to. The places where a void pointer is actually required are very small: parameters to thread functions, and a handful of others places where you need to pass implementation-specific data through a generic function. In every case, the code that accepts the void* parameter should only accept one data type passed via the void pointer, and the type should be documented in comments and slavishly obeyed by all callers.
This might help:
comp.lang.c FAQ list · Question 4.9
Q: Suppose I want to write a function that takes a generic pointer as an argument and I want to simulate passing it by reference. Can I give the formal parameter type void **, and do something like this?
void f(void **);
double *dp;
f((void **)&dp);
A: Not portably. Code like this may work and is sometimes recommended, but it relies on all pointer types having the same internal representation (which is common, but not universal; see question 5.17).
There is no generic pointer-to-pointer type in C. void * acts as a generic pointer only because conversions (if necessary) are applied automatically when other pointer types are assigned to and from void * 's; these conversions cannot be performed if an attempt is made to indirect upon a void ** value which points at a pointer type other than void *. When you make use of a void ** pointer value (for instance, when you use the * operator to access the void * value to which the void ** points), the compiler has no way of knowing whether that void * value was once converted from some other pointer type. It must assume that it is nothing more than a void *; it cannot perform any implicit conversions.
In other words, any void ** value you play with must be the address of an actual void * value somewhere; casts like (void **)&dp, though they may shut the compiler up, are nonportable (and may not even do what you want; see also question 13.9). If the pointer that the void ** points to is not a void *, and if it has a different size or representation than a void *, then the compiler isn't going to be able to access it correctly.
To make the code fragment above work, you'd have to use an intermediate void * variable:
double *dp;
void *vp = dp;
f(&vp);
dp = vp;
The assignments to and from vp give the compiler the opportunity to perform any conversions, if necessary.
Again, the discussion so far assumes that different pointer types might have different sizes or representations, which is rare today, but not unheard of. To appreciate the problem with void ** more clearly, compare the situation to an analogous one involving, say, types int and double, which probably have different sizes and certainly have different representations. If we have a function
void incme(double *p)
{
*p += 1;
}
then we can do something like
int i = 1;
double d = i;
incme(&d);
i = d;
and i will be incremented by 1. (This is analogous to the correct void ** code involving the auxiliary vp.) If, on the other hand, we were to attempt something like
int i = 1;
incme((double *)&i); /* WRONG */
(this code is analogous to the fragment in the question), it would be highly unlikely to work.
Arya's solution can be changed a little to support a variable size:
#include <stdio.h>
#include <string.h>
void swap(void *vp1,void *vp2,int size)
{
char buf[size];
memcpy(buf,vp1,size);
memcpy(vp1,vp2,size);
memcpy(vp2,buf,size); //memcpy ->inbuilt function in std-c
}
int main()
{
int array1[] = {1, 2, 3};
int array2[] = {10, 20, 30};
swap(array1, array2, 3 * sizeof(int));
int i;
printf("array1: ");
for (i = 0; i < 3; i++)
printf(" %d", array1[i]);
printf("\n");
printf("array2: ");
for (i = 0; i < 3; i++)
printf(" %d", array2[i]);
printf("\n");
return 0;
}
The approach/strategy is to minimize use of void* pointers. They are needed in specific cases. If you really need to pass void* you should pass size of pointer's target also.
This generic swap function will help you a lot in understanding generic void *
#include<stdio.h>
void swap(void *vp1,void *vp2,int size)
{
char buf[100];
memcpy(buf,vp1,size);
memcpy(vp1,vp2,size);
memcpy(vp2,buf,size); //memcpy ->inbuilt function in std-c
}
int main()
{
int a=2,b=3;
float d=5,e=7;
swap(&a,&b,sizeof(int));
swap(&d,&e,sizeof(float));
printf("%d %d %.0f %.0f\n",a,b,d,e);
return 0;
}
We all know that the C typesystem is basically crap, but try to not do that... You still have some options to deal with generic types: unions and opaque pointers.
Anyway, if a generic function is taking a void pointer as a parameter, it shouldn't try to dereference it!.