Why use memcpy() in C - c

This might be a very stupid question but i don't understand this:
If i have:
void* a;
void* b;
And I want to implement a generic swap function, why can't I do this:
void swap(void* a, void* b)
{
void* temp = malloc(sizeof(*a));
*a = *b;
*b = *temp;
free(temp);
}
Thank you
I added this later on:
So i understand now why it is impossible but now i have another question:
Since
sizeof(*a)
is undefined, someone told me i could do this:
#define SWAP(a,b) \
{ \
void* temp = malloc(sizeof(*a)); \
memcpy(temp , a , sizeof(*a)); \
memcpy(a, b, sizeof(*a)); \
memcpy(b, temp, sizeof(*a));
free(temp);
}
of course i assume a and b are of the same type.
Why will this solution work?
thank you

You cannot dereference a void *, there is no information about the type of data it's pointing at. So your code won't compile, which is why you cannot do that.
That's the point of void *, it's a "pointer to anything", and there is absolutely no additional information available if you don't add it yourself.
If I have:
char a; /* size 1 */
int b; /* assume size 4 */
and call:
swap(&a, &b); /* assuming it compiled */
All information the function gets is the address of the two variables. There's no way for the function (or the compiler) to magically follow those pointers backward and figure out what the sizes of the pointed-to values are. None.

This way you only "copy" the pointer address but not the actual data. once after you freed temp, y becomes an invalid address. Besides that you're not using a or b in any case

To answer your 2nd question, your SWAP() macro will still NOT work as intended if you pass void* pointers to it. Or for that matter, if you pass two pointers of different types.
It will work for something like this:
int a = 2, b = 3;
char c = '0', d = '1';
SWAP(&a, &b);
SWAP(&c, &d);

Related

Two pointers in C pointing to the same struct - changing the struct from one pointer

I am trying to understand the logic of some code and getting with their use of pointers.
So for example, if two pointers (say A and B) to structures are declared and the equated to each other,
and then the data in a structure is changed through one of the pointers, does it get changed in the second one too or is it just re-written? I guess my question is: will A and B literally point to the same thing or will one point to the copy of the other?
The code does something like this:
somestruct *A;
somestruct *B;
B = A;
A->data = 5;
B->data = 6;
In your example above they will literally point to the same thing.
It is also important to allocate and deallocate memory before and after use however, or else you will get unexpected behaviour and/or segmentation faults.
somestruct *A;
somestruct *B;
A = malloc(sizeof(somestruct));
B = A;
A->data = 5;
B->data = 6;
printf("Data in A: %d", A->data); /* Prints 6 */
printf("Data in B: %d", B->data); /* Also Prints 6 */
...
free(A);
It's also good practice to check the result of malloc and ensure that the operation was successful. This kind of situation can become an issue if for example you want to change the location A points to, and would also like to change the location B points to. Unless you change both, changing one pointers location will not update the other. This is where a double pointer would come in use. EG
somestruct *A;
somestruct **B;
A = malloc(sizeof(somestruct));
B = &A; // Get the address of A
A->member = 5;
printf("Member: %d", (*B)->member); /* Prints 5 */
free(A);
A = malloc(sifeof(somestruct));
A->member = 10;
printf("Member: %d", (*B)->member); /* Prints 10 */
Note that in the double pointer example B does not need updating again.
See the example here: Double Pointer
will A and B literally point to the same thing or will one point to the copy of the other?
A and B will literally point to the same thing
suppose you do something like this
somestruct *A;
somestruct *B;
A = malloc( sizeof(somestruct)) // addded this statement to show that memory allocation is done for A only
B = A;
A->data = 5;
B->data = 6;
this would mean that now pointer B points to the same memory location that A points to, therefore whatever you change (either by using A or B) would change both the pointers data, because essentially its the same data. It is now just being pointed by 2 pointers (namely A and B).
You are changing not the pointers but the object that is referenced to by the pointers. That is it is the object that is been changing using one of the pointers.
For example
#include <stdio.h>
int main()
{
struct A { int i; } a = { 0 };
struct A *p1 = &a;
struct A *p2 = &a;
p1->i = 10;
printf( "%d\n", p2->i );
}
A pointer is not the structure, but simply a memory address (and an instruction to the compiler about the layout of memory), so when you act through the pointer you change the memory. Given another pointer points to the same piece of memory it points to the changed structure.
Of course, if you do something like this:
long *a = malloc(sizeof long);
long *b = a;
and then later:
b = malloc(sizeof long);
then a is not changed, though b is.

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

Simple swap function...why doesn't this one swap?

I'm new to C and still trying to grasp the concept of pointers. I know how to write a swap function that works...I'm more concerned as to why this particular one doesn't.
void swap(int* a, int* b)
{
int* temp = a;
a = b;
b = temp;
}
int main()
{
int x = 5, y = 10;
int *a = &x, *b = &y;
swap(a, b);
printf(“%d %d\n”), *a, *b);
}
You're missing *s in the swap function. Try:
void swap(int* a, int* b)
{
int temp = *a;
*a = *b;
*b = temp;
}
That way, instead of just swapping the pointers, you're swapping the ints that the pointers are pointing to.
Your swap() function does work, after a fashion - it swaps the values of the variables a and b that are local to swap(). Unfortunately, those are distinct from the a and b in main() - so you don't actually see any effect from swapping them.
When thinking about pointers, you need to be clear on a few abstractions.
An object in memory. This can be of any type (and size). An integer object, for example, will occupy 4 bytes in memory (on 32 bit machines). A pointer object will occupy 4 bytes in memory (on 32 bit machines). As should be obvious, the integer object holds integer values; a pointer object holds addresses of other objects.
The C programming language lets symbols (variables) represent these objects in memory. When you declare,
int i;
the symbol (variable) i represents some integer object in memory. More specifically, it represents the value of this object. You can manipulate this value by using i in the program.
&i will give you the address of this object in memory.
A pointer object can hold the address of another object. You declare a pointer object by using the syntax,
int* ptr;
Just like other variables, the pointer variable represents the value of an object, a pointer object. This value just happens to be an address of some other object. You set the value of a pointer object like so,
ptr = &i;
Now, when you say ptr in the program, you are referring to its value, which is the address of i. But if you say *ptr, you are referring to not the value of ptr, but rather the value of the object whose address is in ptr i.e. i.
The problem with your swap function is that you are swapping values of pointers, not the values of objects that these pointers hold addresses for. To get to the values of objects, you would have to use *ptr.
C is a pass-by-value language. Your swap routine doesn't dereference the pointers passed to it, so from main's perspective nothing has happened.
The pointers are passed by value. This means a & b are still a and b when the come back from the function;
try something like this
void swap(int* a, int* b)
{
int temp = *a;
*a = *b;
*b = temp;
}
The right way to do it:
void swap(int* a, int* b)
{
int temp = *a; // Temp is set to the value stored at a (5)
*a = *b; // value stored at a is changed to the value stored at b (10)
*b = temp; // value stored in address b is changed to 5.
}
It does swap. It swaps local pointers a and b inside swap function. It swaps them perfectly fine, as it should.
If you want to swap the values these pointers are pointing to, you should re-implement your swap function accordingly, i.e. make it swap the pointed values, not the pointers.
Umm maybe using this
void swap(int** a, int** b)
{
int** temp = a;
a = b;
b = temp;
}
int main()
{
int x = 5, y = 10;
int *a = &x, *b = &y;
swap(&a, &b);
printf(“%d %d\n”), *a, *b);
}
Without using a third variable (temp)
void swap(int* a,int* b)
{
// a = 10, b = 5;
*a = *a + *b; // a now becomes 15
*b = *a - *b; // b becomes 10
*a = *a - *b; // a becomes 5
}
zildjohn1's answer is the easiest and clearest way to do it. However if you insist on swapping the pointers, then you have to pass the pointer to the pointer because the pointer itself is passed by value.
You need to send the address of a and b for swap function so while calling swap function you must call ass swap (&a,&b)
So that you pass the address, and alter the address
#define SWAP(a,b) ((a)=(b)+(a),(b)=(a)-(b),(a)=(a)-(b))
Works good.

Swapping objects using pointers

I'm trying to swap objects for a homework problem that uses void pointers to swap objects. The declaration of my function has to be:
void swap(void *a, void *b, size_t size);
I'm not looking for the exact code how to do it so I can figure it out by myself, but I'm not sure if I understand it correctly. I found that one problem is by doing:
void *temp;
temp = a;
a = b;
b = temp;
only changes what the pointers point to. Is that correct? If it is correct, why doesn't swapping pointers actually change the contents between *a and *b. Because if your pointer points to something different, couldn't you dereference it and the objects would now be different?
Similarly, just switching the values like:
void *temp;
*temp = *a;
*a = *b;
*b = *temp;
Is not correct either, which I'm not sure why. Because again, it seems to me that the content is switched.
Does swapping objects mean complete swapping of memory and value of what a pointer points to?
So it seems like I have to use malloc to allocate enough space for my swap. If I allocate enough memory for one object, assuming they are the same size, I don't really see how it is different than the other two methods above.
void *temp = malloc(sizeof(pa));
// check for null pointer
temp = a;
// do something I'm not sure of since I don't quite get how allocating space is any
// different than the two above methods???
Thanks!
Swapping pointers does not change the pointed-to values. If it did, that would be like swapping address labels on envelopes moving me into your house and you into mine.
You were nearly there:
void swap(void *a, void *b, size_t size) {
char temp[size]; // C99, use malloc otherwise
// char serves as the type for "generic" byte arrays
memcpy(temp, b, size);
memcpy(b, a, size);
memcpy(a, temp, size);
}
The memcpy function copies memory, which is the definition of objects in C. (Called POD or plain ol' data in C++, to compare.) In this way, memcpy is how you do assignment without caring about the type of the object, and you could even write other assignments as memcpy instead:
int a = 42, b = 3, temp;
temp = b;
b = a;
a = temp;
// same as:
memcpy(&temp, &b, sizeof a);
memcpy(&b, &a, sizeof a);
memcpy(&a, &temp, sizeof a);
This is exactly what the above function does, since you cannot use assignment when you do not know the type of the object, and void is the type that stands in for "unknown". (It also means "nothing" when used as function return type.)
As a curiosity, another version which avoids malloc in common cases and doesn't use C99's VLAs:
void swap(void *a, void *b, size_t size) {
enum { threshold = 100 };
if (size <= threshold) {
char temp[threshold];
memcpy(temp, b, size);
memcpy(b, a, size);
memcpy(a, temp, size);
}
else {
void* temp = malloc(size);
assert(temp); // better error checking desired in non-example code
memcpy(temp, b, size);
memcpy(b, a, size);
memcpy(a, temp, size);
free(temp);
}
}
To answer your first question, let's fill in some values to see what is happening:
void* a = 0x00001000; // some memory address
void* b = 0x00002000; // another memory address
/* Now we'll put in your code */
void* temp; // temp is garbage
temp = a; // temp is now 0x00001000
a = b; // a is now 0x00002000
b = temp; // b is now 0x00001000
So at the end of those statements, the pointer's values have been swapped, that is, whatever a was pointing to is now pointed to by b, and vice versa. The values of what those pointers are pointing to are unmodified, it's just that now their memory addresses are being held by different pointers.
To answer your second question, you cannot dereference a void*. The reason for this is that void has no size, so to try and dereference or assign to something that has no size is nonsensical. Thus, void* is a way of guaranteeing you can point to something, but you will never know what that something is without more information (hence the size parameter to your routine).
From there, knowing the pointer and the size of the data the pointer points to, you can use a routine like memcpy to move the data pointed to by one pointer into the location pointed to by another.
Parameters are like local variables, with values copied into them before the function starts executing. This prototype:
void swap(void *a, void *b, size_t size);
Means that the two addresses are copied into new variables called a and b. So if you change what is stored in a and b, nothing you do will have an any effect after swap returns.
I had a question similar to this for my C course. I think memcopy is probably best but you can also try this:
typedef unsigned char * ucp;
void swap(void *a, void *b, int size){
ucp c=(ucp)a;
ucp d=(ucp)b;
for(int i=0; i<size; i++){
int temp=(int)c[i];
c[i]=(int)d[i];
d[i]=temp;
}
}
Basically what this does is cast both pointers to an unsigned char pointer type. Then you increment the pointer, which in the case of an unsigned char, increments one BYTE at a time. Then what you're doing is basically copying the contents of each byte at a time in memory. If anyone wants to correct or clarify on this I would appreciate it too.
First of all, note that any changes to the pointers inside the function won't be propagated to outside the function. So you're going to have to move memory around.
The easiest way to do that is with memcpy - allocate a buffer on the stack, memcpy the appropriate size from a into it, memcpy from b to a, and one last memcpy from temp into b.
If you were writing a function to swap two integers, given pointers to them, your solution of swapping the values pointed to would work. However, consider the situation with
struct {
int a;
int b;
} a, b;
swap(&a, &b, sizeof(a));
You need to figure out a way to swap the contents of each value passed without any knowledge of what they actually consist of.
You're close.
The problem is: you are "swapping" only pointers a and b which are local variables in the function.
I assume outside of the function you have some variables, let's call them:
void *x = ...;
void *y = ...;
When you call:
swap(x, y, some_size);
a and b points to the same objects as x and y respectively. Now, when you swap what a and b points too, x and y are still pointing to what they where pointing before.
To change what memory x and y points you would have to pass a pointer to the x variable, so a pointer to a pointer :)
Because you can't change function declaration you can only swap the content of the memory where x (and a) and y (and b) points to. Some solutions are in other answers :) Generally memcpy is what you want.
To have any real effect, you need to do the equivalent of the second block you mentioned:
void *temp;
*temp = *a;
*a = *b;
*b = *temp;
The problem here is that 'void' doesn't have a size, so you can't assign 'void's as they stand. You need to allocate space for temp to point at, then copy the values using something like memcpy().
To change the pointer inside and keep it outside, you have to pass the pointer by reference or a double pointer.
If your function has to be like:
void swap(void *a, void *b, size_t size);
I suppose that you have to implement something like:
void * temp;
temp = malloc(size);
memcpy(temp,a,size);
memcpy(a,b,size);
memcpy(b,temp,size);
free(temp);
We need not use memcpy for swapping two pointers, following code works well(tested for swapping int* and char* strings):
void swap(void **p, void **q)
{
void *t = *p;
*p = *q;
*q = t;
}

Copying arrays of structs in C

It's been a long since I don't use C language, and this is driving me crazy. I have an array of structs, and I need to create a function which will copy one array to another (I need an exact copy), but I don't know how to define the function call. I guess I need to use pointers, but when I try it gives me an error.
struct group{
int weight;
int x_pos;
int y_pos;
int width;
int height;
};
struct group a[4];
struct group b[4];
copySolution(&a, &b);
That last declaration send me an error. As I said, it's been a long since programming in C, so I'm a bit lost right now :(
That should do it:
memcpy(&b, &a, sizeof(a));
EDIT: By the way: It will save a copy of a in b.
As Johannes Weiß says, memcpy() is a good solution.
I just want to point out that you can copy structs like normal types:
for (i=0; i<4; i++) {
b[i] = a[i]; /* copy the whole struct a[i] to b[i] */
}
This has a feel of poorly masqueraded homework assignment... Anyway, given the predetermined call format for copySolution in the original post, the proper definition of copySolution would look as follows
void copySolution(struct group (*a)[4], struct group (*b)[4])
{
/* whatever */
}
Now, inside the copySolution you can copy the arrays in any way you prefer. Either use a cycle
void copySolution(struct group (*a)[4], struct group (*b)[4])
{
const struct group *pb, *pbe;
struct group *pa;
for (pa = *a, pb = *b, pbe = pb + sizeof *b / sizeof **b;
pb != pbe;
++pa, ++pb)
*pa = *pb;
}
or use memcpy as suggested above
void copySolution(struct group (*a)[4], struct group (*b)[4])
{
memcpy(b, a, sizeof *b);
}
Of course, you have to decide first which direction you want your arrays to be copied in. You provided no information, so everyone just jumped to some conclusion.
In my case previous solutions did not work properly! For example,
#Johannes Weiß's solution did not copy "enough" data (it copied about half of the first element).
So in case, somebody needs a solution, that will give you correct results, here it is:
int i, n = 50;
struct YourStruct *a, *b;
a = calloc(n, sizeof(*a));
b = malloc(n * sizeof(*b));
for (i = 0; i < n; ++i) {
// filling a
}
memcpy(b, a, n * sizeof(*a)); // <----- see memcpy here
if (a != NULL) free(a);
a = calloc(n*2, sizeof(*a));
memcpy(a, b, n * sizeof(*b)); // <------ see memcpy here again
Some notes, I used calloc for a, because in the '// filling a' part I was doing operations that required initialized data.
The compiler has no information about the size of the array after passing them as pointer into a function. So you often need a third parameter: The size of the arrays to copy.
A solution (without any error checking) could be:
void copySolution(struct group* a, struct group* b, size_t size) {
memcpy(a, b, size * sizeof(*a));
}
The easiest way is probably
b=a
although a solution with memcpy() will also work.

Resources