I'm beginning to learn C and read following code:
public void** list_to_array(List* thiz){
int size = list_size(thiz);
void **array = malloc2(sizeof(void *) * size);
int i=0;
list_rewind(thiz);
for(i=0; i<size; i++){
array[i] = list_next(thiz);
}
list_rewind(thiz);
return array;
}
I don't understand the meaning of void**. Could someone explain it with some examples?
void** is a pointer to a pointer to void (unspecified type). It means that the variable (memory location) contains an address to a memory location, that contains an address to another memory location, and what is stored there is not specified. In this question's case it is a pointer to an array of void* pointers.
Sidenote: A void pointer can't be dereferenced, but a void** can.
void *a[100];
void **aa = a;
By doing this one should be able to do e.g. aa[17] to get at the 18th element of the array a.
To understand such declarations you can use this tool and might as well check a related question or two.
void** is a pointer to void*, or a pointer to a void pointer if you prefer!
This notation is traditionally used in C to implement a matrix, for example. So, in the matrix case, that would be a pointer to an array of pointers.
Normally void * pointers are used to denote a pointer to an unknown data type. In this case your function returns an array of such pointers thus the double star.
In C, a pointer is often used to reference an array. Eg the following assignment is perfectly legal:
char str1[10];
char *str2 = str1;
Now when void is used, it means that instead of char you have a variable of unknown type.
Pointers to an unknown data type are useful for writing generic algorithms. Eg. the qsort function in standard C library is defined as:
void qsort ( void * base,
size_t num,
size_t size,
int ( * comparator )
( const void *, const void * ) );
The sorting algorithm itself is generic, but has no knowledge of the contents of the data. Thus the user has to provide an implementation of a comparator that can deal with it. The algorithm will call the comparator with two pointers to the elements to be compared. These pointers are of void * type, because there is now information about the type of data being sorted.
Take a look at this thread for more examples
http://forums.fedoraforum.org/showthread.php?t=138213
void pointers are used to hold address of any data type. void** means pointer to void pointer. Void pointers are used in a place where we want a function should receive different types of data as function argument. Please check the below example
void func_for_int(void *int_arg)
{
int *ptr = (int *)int_arg;
//some code
}
void func_for_char(void *char_arg)
{
char *ptr = (char *)char_arg;
//some code
}
int common_func(void * arg, void (*func)(void *arg))
{
func(arg);
}
int main()
{
int a = 10;
char b = 5;
common_func((void *)&a, func_for_int);
common_func((void *)&b, func_for_char);
return 0;
}
Related
I want to loop over arrays in a type-independent manner by casting a void pointer to an array of objects of arbitrary byte size. I know the size of the array and the size of its items, but not the type of the items. Is there a safe and portable way of doing this?
All I can think of at the moment is to create a struct with one member, a char array of the required size. But I'm not sure how safe and portable this is as a solution, due to possibility of alignment issues and possibly other problems I haven't thought of.
Example code of what I want to do:
void myFunc(void * arrV, int len, size_t arrSize, size_t itemSize) {
// type definition, for array item of size itemSize
struct xxxx {char[itemSize];};
struct xxxx * arr = (struct xxxx *) arrV;
for (int i = 0; i < len; i++) {
if (i == 100) {
struct xxxx arrItem = arr[i];
// do something with arrItem;
}
}
}
Edit: question title edited as it was phrased incorrectly.
Use malloc to allocate memory
void * itemArr = malloc(arrSize * itemSize);
malloc dynamically allocates memory equal to the size of its first parameter (in bytes).
Once you are done with using it, you can free that memory to make it usable again.
free(itemArr);
Edit: Ok here is trial 2
I do not think this:
struct xxxx {char[itemSize];};
is valid syntax in C, you need to have an identifier.
Also my argument still stands, if you want to create an object from an unknown type of arbitrary size, you can use malloc instead of a normal array. Use malloc, cast it to a void* or char*, and treat it as an unknown data type. A struct, or for that matter data types, are all abstractions. You can treat any piece of memory as a non-standard data type. Also as far as I know malloc shouldn't cause alignment issues as malloc pointers are always aligned
The size of a structure has to be known at compile time. You can have a flexible array member (FAM and more FAM) in a structure, but that doesn't help, not least because the size of the structure doesn't include the size of the FAM. Your attempt to create a type struct xxxx with a size determined at run time is doomed.
The C standard has two functions that process arrays of arbitrary type and size: bsearch() and qsort(). They use void *base to point to the start of the array, size_t count to specify how many elements are in the array and size_t size to specify the size of each element:
void qsort(void *base, size_t count, size_t size,
int (*compar)(const void *, const void *));
These functions both take a pointer to a function that compares two values in the array by whatever mechanism the function chooses.
To achieve your goal, you will need to emulate them. You've not specified how you expect to process the values in the array, and that would give you headaches unless you adopt a similar technique where you pass a pointer to each element of the array to a function.
You can process an array of arbitrary type and size with ordinary pointer arithmetic. Despite what the GCC compiler permits, Standard C says you can't do arithmetic on void * values, but you can do arithmetic on char * values. As long as the size of the items is the result of sizeof(TheActualType), you can step through data that is appropriately aligned. I'm assuming that in your interface, arrSize == len * itemSize (see also my comment), though that's barely critical as I redesign the interface to your function to more closely match the standard functions. I add a callback function which is given a void * argument that can be safely cast to whatever type is being processed:
void ProcessArray(void *base, size_t count, size_t size, void (*processor)(void *))
{
char *array = base;
for (int i = 0; i < len; i++)
{
(*processor)(array + i * itemSize);
}
}
The function pointer should be of the type shown. Many people take the shortcut of defining a processing function such as void ProcessingFunction(SomeType *arg); and passing that to a function. That includes such prestigious references as Brian W Kernighan and Dennis M Ritchie
The C Programming Language, 2nd Edn (1988). But the C standard says (in §6.3.2.3 (Conversions of) Pointers) that calling a pointer to a function with the wrong type is undefined behaviour. So, strictly, you should not pass such a function to a function like ProcessArray(). You need a function like:
void ProcessingFunction(void *arg)
{
SomeType *ptr = arg; /* Cast not necessary in C */
…process data using ptr->member…
}
If need be, you can pass a 'context' pointer to the functions to convey information other than the element being processed to the processing function:
void ProcessArrayWithContext(void *base, size_t count, size_t size, void (*processor)(void *arg, void *context), void *context)
{
char *base = arrV;
for (int i = 0; i < len; i++)
{
(*processor)(base + i * itemSize, context);
}
}
And then:
void ProcessingFunctionWithContext(void *arg, void *context)
{
SomeType *ptr = arg; /* Cast not necessary in C */
ContextInfo *ctxt = context;
…process data using ptr->member and ctxt->info…
}
There is precedent for this with the non-standard qsort_r() functions defined by Linux and BSD (macOS). However, be aware that the BSD and Linux interfaces to qsort_r() are different. The Linux version looks like:
void qsort_r(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *, void *),
void *arg);
The comparator takes the context as the third, non-const argument, and qsort_r() passes arg as that third argument. The BSD version looks like:
void qsort_r(void *base, size_t nel, size_t width, void *thunk,
int (*compar)(void *, const void *, const void *));
The comparator takes the context as the first, non-const argument, and the context is passed before the pointer to the comparator.
In the Linux code, the function effectively contains:
void *v1 = …;
void *v2 = …;
int rc;
if ((rc = (*compar)(v1, v2, arg)) < 0)
…
else if (rc > 0)
…
else
…
The BSD effectively contains:
void *v1 = …;
void *v2 = …;
int rc;
if ((rc = (*compar)(arg, v1, v2)) < 0)
…
else if (rc > 0)
…
else
…
See also Pass extra parameter to comparator for qsort()?.
Obviously, the callback (processing) function could be given other types. For example, you might have it return a value of type int and the loop could exit early if the value returned is not 0, or if it is 0. The options are legion.
I want to loop over arrays in a type-independent manner by casting a void pointer to an array of objects of arbitrary byte size. I know the size of the array and the size of its items, but not the type of the items. Is there a safe and portable way of doing this?
It depends on how portable you need it to be. Your suggestion of an defining a structure type containing an array of the desired length is not viable for two reasons:
In standard C, structure types may not be defined as containing variable-length arrays, and
There is no portable way to ensure that the structure type would not contain padding (which would make its size wrong).
Additionally, the variable-length array feature is optional in C11 and C17 (though it is a mandatory in C99, and some form of it might return to mandatory status in C2X). But if you are willing to rely on VLAs then you can use them more directly for your purpose:
void myFunc(void *arrV, int len, size_t arrSize, size_t itemSize) {
char (*items)[itemSize] = arrV; // pointer to (variable-length) array
for (int i = 0; i < len; i++) {
// ... do something with items[i] ...
}
}
If you don't want to depend on VLAs then the conventional way that functions such as qsort() do it is to convert the void * to a char * and perform appropriate arithmetic with that:
void myFunc(void *arrV, int len, size_t arrSize, size_t itemSize) {
char *items = arrV;
for (int i = 0; i < len; i++) {
char *item_start = items + (i * itemSize);
// ... do something with *item_start
}
}
I tried to implement a form of collections-library. I do it all the time, when learning a new language, because it teaches most of the language details.
So, I started with a form of "generic" dynamic array. Well it is not really generic, because it just holds pointers to the actual data.
But to be honest, I don't fully understand, why I need a double void pointer here.
The Vector struct defined in my header file (I declared every method and #include in the header file, but I omitted this here to keep the code readable. I also ommitted some bounds checks)
typedef struct {
size_t capacity; //the allocated capacity
size_t length; //the actual length
void **data; //here I don't fully understand, why I need a double pointer.
} Vector;
Here is my implementation of a few methods, where the compiler complains when I use a single void pointer in my struct, so void *data instead of void **data.
#include "utils.h"
const size_t INITIAL_SIZE = 16;
//Creates a new empty vector.
Vector *vec_new(void) {
printf("sizeof Vector is: %ld", sizeof(Vector));
Vector *vec = malloc(sizeof(Vector));
vec->length = 0;
vec->capacity = INITIAL_SIZE;
void *data = calloc(INITIAL_SIZE, sizeof(void*));
if(data == NULL) {
free(vec->data);
fprintf(stderr, "Error allocating memory.");
exit(EXIT_FAILURE);
}
vec->data = data;
return vec;
}
//This method appends the specified value at the end of the vector.
void vec_push(Vector *vec, void *data) {
if(vec->length == vec->capacity-1) {
vec_resize(vec);
}
vec->data[vec->length] = data;
vec->length += 1;
}
//gets the value at the specified index or NULL if index is out of bounds.
void *vec_get(Vector *vec, size_t index) {
return vec->data[index];
}
//Resizes the vector to 1.5x its current capacity.
void vec_resize(Vector *vec) {
vec->capacity *= 1.5;
void *data = realloc(vec->data, sizeof(void*) * vec->capacity);
if(data == NULL) {
free(vec->data);
fprintf(stderr, "Error allocating memory.");
exit(EXIT_FAILURE);
}
vec->data = data;
}
It seems like here is where the magic happens, which i do not yet understand:
void *data = malloc(...);
vec->data = data;
Malloc/calloc return a void pointer, so i either have to declare an actual type or just using the returned void pointer. So the first line is clear.
vec->data is, under the assumption I do not use a double pointer in the struct definition equivalent to (*vec).data as far as I understand it. So basically this line should assing a void pointer to a void pointer.
Can maybe someone explain it to me in simple terms, why exactly a single void pointer is not enough here or where I might misunderstand something.
But to be honest, I don't fully understand, why I need a double void pointer here.
Some background first - maybe you already know that:
A pointer of the type someType * is a pointer to some variable of the type someType or to an array of variables of the type someType.
A pointer of the type someType ** is a pointer to a variable of the type someType * - this means: A pointer to a pointer to a variable of the type someType.
A pointer of the type void * is a pointer to anything; because the compiler does not know to what kind of element this pointer points to, it is not possible to access such an element directly.
In contrast to this, it is known what variable a pointer of the type void ** points to: It points to a variable of the type void *.
Why you need void** in this position:
The key are the lines:
vec->data[vec->length] = data;
...
return vec->data[index];
In these lines, the code accesses the data vec->data points to. For this reason, vec->data cannot be void * but it must be xxx * while xxx is the type of data the pointer vec->data points to. And because vec->data points to a pointer of the type void *, xxx is void * so xxx * is void **.
vec->data = data;
Your observation is correct: vec->data is of the type void ** and data is of the type void *.
The reason is that malloc() returns some memory and the compiler does not know which kind of data is stored in this memory. So the value returned by malloc() is void * and not void **.
In the automotive industry, you would use an explicit pointer cast like this:
vec->data = (void **)data;
The expression (xxx *)y tells the compiler that the pointer y points to some data of the type xxx. So (void **) tells the compiler that the pointer points to an element of the type void *.
However, in desktop applications you often don't write the (void **).
If you have a pointer of the type
T *p1;
where T is some type specifier as for example void then pointer to this pointer will be declared like
T **p2 = &p1.
In this call of calloc
calloc(INITIAL_SIZE, sizeof(void*))
you are going to allocate an array of pointers of the type void *. The function returns a pointer to the first element of the allocated array. So you need to write
void **data = calloc(INITIAL_SIZE, sizeof(void*));
To make it more clear let's assume that you need to allocate dynamically an integer array. In this case you will write
int *data = calloc( INITIAL_SIZE, sizeof( int ) );
So dereferencing the pointer data like *data you will get an object of the type int more precisely the first element of the allocated array.
When elements of the array have the type void * then dereferencing the pointer data like *data you must to get a pointer of the type void * (the first element of the allocated array). So to make the operation correct the pointer data shall have the type void **.
int main()
{
int b = 12;
void *ptr = &b;
printf("%d", *ptr);
return 0;
}
I expected for this code to print 12, but it does not.
if instead of void pointer, we define int pointer it would work.
I wanted to know how can we use void pointer and print the address allocated to it and the amount saved in it?
Dereferencing a void * doesn't make sense because it has no way of knowing the type of the memory it points to.
You would need to cast to pointer to a int * and then dereference it.
printf("%d", *((int *)ptr));
void pointers cannot be dereferenced.it will give this warning
Compiler Error: 'void' is not a pointer-to-object type*
so, you have to do it like this.
#include<stdio.h>
int main()
{
int b = 12;
void *ptr = &b;
printf("%d", *(int *)ptr);
return 0;
}
If p has type void *, then the expression *p has type void, which means "no value". You can't pass a void expression to printf for the %d conversion specifier (or any other conversion specifier).
In order to dereference a void *, you must first convert it to a pointer of the appropriate type. You can do it with a cast:
printf( "%d\n", *(int *) ptr );
or assign it to a pointer of the appropriate type:
int *p = ptr;
printf( "%d\n", *p );
The rules around void pointers are special such that they can be assigned to other pointer types without an explicit cast - this allows them to be used as a "generic" pointer type. However, you cannot directly examine the thing a void pointer points to.
A schoolbook example of when void pointers are useful is qsort.
This is the signature:
void qsort(void *base,
size_t nitems,
size_t size,
int (*compar)(const void *, const void*)
);
base is just a pointer to the first element. The reason it's a void pointer is because qsort can be used for any list, regardless of type. nitems is number of items (doh) in the list, and size is the size of each element. Nothing strange so far.
But it does also take a fourth argument, which is a function pointer. You're supposed to write a custom compare function and pass a pointer to this function. This is what makes qsort able to sort any list. But since it's supposed to be generic, it takes two void pointers as argument. Here is an example of such a compare function, which is a bit bloated for clarity:
int cmpfloat(const void *a, const void *b) {
const float *aa = (float*) a;
const float *bb = (float*) b;
if(*aa == *bb) {
return 0;
} else if(*aa > *bb) {
return 1;
} else {
return -1;
}
}
Pretty clear what is going on. It returns positive number if a>b, zero if they are equal and negative if b>a, which is the requirements. In reality, I'd just write it like this:
int cmpfloat(const void *a, const void *b) {
return *(float*)a - *(float*)b;
}
What you do with this is something like:
float arr[5] = {5.1, 3.4, 8.9, 3.4, 1.3};
qsort(arr, 5, sizeof *arr, cmpfloat);
Maybe it's not completely accurate to say that void pointers are used instead of templates, generic functions, overloaded functions and such, but they have similarities.
I am learning C from "C by K&R". I was going through Function pointers section.There was an example to sort an array of strings using function pointers and void pointers.(to be specific,on page 100). I have a fair understanding of function pointers and void pointers.
The example given there calls
qsort((void**) lineptr, 0, nlines-1,(int (*)(void*,void*))(numeric ? numcmp : strcmp));
And it seemlessly uses void ptr,like as below to compare and swap.
I understand that it takes array of pointer and each element by itself is a void pointer to the string. How is it possible to compare,swap a void ptr with another.
void sort(void *v[],int i,int j)
{
id *temp;
temp = v[i];
v[i] = v[j];
v[j] = temp;
}
Can anyone explain the concept behind this.
How is it possible to compare, swap a void ptr with another?
Compare: comparing a void ptr with each other is meaningless, as their values are addresses.
Swap: A pointer is a variable holding an address. By changing a pointer's value you change the address it points to. Data itself is not even considered here.
Note: void pointers does not interpret the data they are pointing to. That is why you need explicit type conversion when you dereference them, such that there is a correspondence between the data they are pointing to and the variable this data is assign to.
Remember that pointers are just variables that store a memory address. If there's not any conflict between types I can't see why this shouldn't be possible!
The only difference between a void ptr and another is that you must pay attention only during the dereference (you need a cast to complete it)
For example:
void *ptr;
int m, n;
ptr = &n;
m = *((int *) ptr);
Anyway, ignoring this particular, you can work with void pointer normally.. You can, as your code shows, for example swap them just as they were int or other types variables
The function pointer required by qsort() has the following type
int (*compar)(const void *, const void *);
it means, that you can pass pointers of any type to this function since in c void * is converted to any poitner type without a cast.
Inside a comparision funcion, you MUST "cast"1 the void * poitners in order to be able to dereference them. Because a void * pointer cannot be dereferenced.
Swaping pointers is the correct way to sort an array of poitners, just like swaping integers would be the way to sort an array of integers. The other way, with an array of strings for example, would be to copy the string to a temporary buffer and perform a swap in terms of copying the data, and I think there is no need to explain why this is bad.
1
When I say cast I don't mean that you need to "cast", just convert to the appropriate poitner type. For example:
int compare_integers(const void *const x, const void *const y)
{
int *X;
int *Y;
X = x;
Y = y;
return (*X - *Y);
}
although it's of course possible to write return (*((int *) x) - *((int *) y)).
In this type of situation, it's often helpful to typedef to gain a better understanding. For illustration purposes, you could do
typedef void* address; //to emphasize that a variable of type void* stores an address
Now your swap function looks less daunting,
void swap(address v[],int i,int j) //takes an array of addresses v
{
address temp;
temp = v[i];
v[i] = v[j];
v[j] = temp;
}
A void *, however, contains no information regarding the type of object it points to. So before dereferencing it, you need to cast it to the right type, which is what strcmp and numcmp do, e.g.,
int strcmp(address a1, address a2) { //assumes a1 and a2 store addresses of strings
char *s1 = a1;
char *s2 = a2;
//s1 and s2 can be dereferenced and the strings they point to can be compared
}
This is from a 'magic' array library that I'm using.
void
sort(magic_list *l, int (*compare)(const void **a, const void **b))
{
qsort(l->list, l->num_used, sizeof(void*),
(int (*)(const void *,const void *))compare);
}
My question is: what on earth is the last argument to qsort doing?
(int (*)(const void *, const void*))compare)
qsort takes int (*comp_fn)(const void *,const void *) as it's comparator argument, but this sort function takes a comparator with double pointers. Somehow, the line above converts the double pointer version to a single pointer version. Can someone help explain?
That's exactly what the cast you quoted does: it converts a pointer of type
int (*)(const void **, const void **)
to a pointer of type
int (*)(const void *, const void *)
The latter is what is expected by qsort.
Thing like this are encountered rather often in bad quality code. For example, when someone wants to sort an array of ints, they often write a comparison function that accepts pointers to int *
int compare_ints(const int *a, const int *b) {
return (*a > *b) - (*a < *b);
}
and when the time comes to actually call qsort they forcefully cast it to the proper type to suppress the compiler's complaints
qsort(array, n, sizeof *array, (int (*)(const void *,const void *)) compare_ints);
This is a "hack", which leads to undefined behavior. It is, obviously, a bad practice. What you see in your example is just a less direct version of the same "hack".
The proper approach in such cases would be to declare the comparison function as
int compare_ints(const void *a, const void *b) {
int a = *(const int *) a;
int b = *(const int *) b;
return (a > b) - (a < b);
}
and then use it without any casts
qsort(array, n, sizeof *array, compare_ints);
In general, if one expects their comparison functions to be used as comparators in qsort (and similar functions), one should implemnent them with const void * parameters.
The last argument to qsort is casting a function pointer taking double pointers, to one taking single pointers that qsort will accept. It's simply a cast.
On most hardware you can assume that pointers all look the same at the hardware level. For example, in a system with flat 64bit addressing pointers will always be a 64bit integer quantity. The same is true of pointers to pointers or pointers to pointers to pointers to pointers.
Therefore, whatever method is used to invoke a function with two pointers will work with any function that takes two pointers. The specific type of the pointers doesn't matter.
qsort treats pointers generically, as though each is opaque. So it doesn't know or care how they're dereferenced. It knows what order they're currently in and uses the compare argument to work out what order they should be in.
The library you're using presumably keeps lists of pointers to pointers about. It has a compare function that can compare two pointers to pointers. So it casts that across to pass to qsort. It's just syntactically nicer than, e.g.
qsort(l->list, l->num_used, sizeof(void*), compare);
/* elsewhere */
int compare(const void *ptr1, const void *ptr2)
{
// these are really pointers to pointers, so cast them across
const void **real_ptr1 = (const void **)ptr1;
const void **real_ptr2 = (const void **)ptr2;
// do whatever with real_ptr1 and 2 here, e.g.
return (*real_ptr2)->sort_key - (*real_ptr1)->sort_key;
}
It is casting a function pointer. I imagine that the reason is so that compare can be applied to the pointers that are dereferenced rather than whatever they are pointing to.
(int (*)(const void *,const void *))compare is a C style cast to cast the function pointer compare to a function pointer with two const void * args.
The last argument is a function pointer. It specifies that it takes a pointer to a function that returns an int and takes two const void ** arguments.