Swap function using void pointers [duplicate] - c

This question already has answers here:
Swapping objects using pointers
(10 answers)
Closed 7 years ago.
I want to make a swap function that can be generically used for any data type. I know that the following function works for ints:
void swap(void *a, void *b)
{
int temp;
temp = *(int*)a;
*(int*)a = *(int*)b;
*(int*)b = temp;
}
and this works for strings:
void swap(void *a, void *b)
{
void *temp;
temp = *(void**)a;
*(void**)a = *(void**)b;
*(void**)b = temp;
}

If you pass the size of the pointee along, too (like in qsort), then you can do it:
void swap(void * a, void * b, size_t len)
{
unsigned char * p = a, * q = b, tmp;
for (size_t i = 0; i != len; ++i)
{
tmp = p[i];
p[i] = q[i];
q[i] = tmp;
}
}
Usage:
struct Qux x, y;
swap(&x, &y, sizeof(Qux));
(You might want to add restrict qualifiers to the pointers, or otherwise a test for self-swapping.)

You should read the C FAQ list at least once. It is good to see what people have pondered over time.
Why can't I perform arithmetic on a void * pointer? is relevant to your question:
The compiler doesn't know the size of the pointed-to objects. (Remember that pointer arithmetic is always in terms of the pointed-to size; see also question 4.4.) Therefore, arithmetic on void *'s is disallowed (though some compilers allow it as an extension). Before performing arithmetic, convert the pointer either to char * or to the pointer type you're trying to manipulate (but see also questions 4.5 and 16.7).
Also relevant is 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 ** ...:
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.

Here's another answer:
void swap(void *a, void *b, size_t width)
{
void *temp = malloc(width);
memcpy(temp, b, width);
memcpy(b, a, width);
memcpy(a, temp, width);
free(temp);
}

Related

why trying to deference void pointer does not work?

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.

C function pointers

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
}

Swap any type of two variables in c [duplicate]

This question already has answers here:
Implement generic swap macro in C [duplicate]
(6 answers)
Closed 9 years ago.
Is there any logic in c which can swap any type of two variables. i.e int, float, sequence of character.
I can think of a logic of storing every type of variables as sequence of characte and swap it like normal string but i does not its good idea.
Let's see how you'd do this for two char variables. You'd do something like this.
void swap(char* a, char* b)
{
char tmp = *a;
*a = *b;
*b = tmp;
}
For two int variables:
void swap(int* a, int* b)
{
int tmp = *a;
*a = *b;
*b = tmp;
}
And so on. Now, for catering to any type of variable, you'd be tempted to do:
void swap(void* a, void* b)
{
// ...
}
But you'd need to allocate a space of a parameterized size. So, you'll have to first receive that size as a parameter:
void swap(void* a, void* b, size_t s)
{
// ...
}
...which you'll pass as an argument using a sizeof expression. And you'll need to allocate said space and do assignments (copies) using that. Off the top of my head, malloc/free and memcpy come to mind, so a crude way to do what we did above for char and int, but this time with a parameterized size, would be:
void swap_any(void* a, void* b, size_t s){
void* tmp = malloc(s);
memcpy(tmp, a, s);
memcpy(a, b, s);
memcpy(b, tmp, s);
free(tmp);
}
As I described, this is a little crude. You could try doing it with alloca (which allocates on the stack) and no free.
Alternatively, you could do it with a macro, since you can pass a type (instead of a size_t) to a macro - because macros essentially work using text replacement. Then, you can obviously create the temporary variable type by name, like this:
#define swap_m(a, b, t) { t tmp = a; a = b; b = tmp; }
Obviously, if you don't want to pass any information at all about the involved types, you'd have to be more creative about it.
You can use a macro for that, but it won't work for everything:
#define SWAP(a,b) { __typeof__(a) temp; temp = a; a = b; b = temp; }

What does the declaration void** mean in the C language?

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;
}

What does this C syntax mean?

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.

Resources