cast in memcpy()

  • Thread starter Amarendra GODBOLE
  • Start date
A

Amarendra GODBOLE

Hi,

I am a bit confused over the correct usage of memcpy(). Kindly help me
clear the confusion.

The linux manpage for memcpy(3) gives me the following prototype of
memcpy(3):
#include <string.h>
void *memcpy(void *dest, const void *src, size_t n);

Now, I have a char array (char arr[256]), and a pointer to a structure
(PSMessage *p). I have to memcpy() the contents of this structure to
the char array. I am doing it like this:

memcpy(arr, p, sizeof *p);

Someone tells me -- this is an incorrect usage, you either need to do
memcpy(arr, (char *)p, sizeof *p);
or
memcpy((void *)arr, (void *)p, sizeof *p);

Do I need the cast here ? Or the way I am trying to do it is correct ?
I have not tested the code, so I am not sure of it either.

Thanks in advance.

Cheers,
Amarendra
 
B

Ben Pfaff

memcpy(arr, p, sizeof *p);

Someone tells me -- this is an incorrect usage, you either need to do
memcpy(arr, (char *)p, sizeof *p);
or
memcpy((void *)arr, (void *)p, sizeof *p);

Your informant is wrong. No such casts are necessary in C.
 
M

Martin Ambuhl

Amarendra said:
Hi,

I am a bit confused over the correct usage of memcpy(). Kindly help me
clear the confusion.

The linux manpage for memcpy(3) gives me the following prototype of
memcpy(3):
#include <string.h>
void *memcpy(void *dest, const void *src, size_t n);

Now, I have a char array (char arr[256]), and a pointer to a structure
(PSMessage *p). I have to memcpy() the contents of this structure to
the char array. I am doing it like this:

memcpy(arr, p, sizeof *p);

Someone tells me -- this is an incorrect usage, you either need to do
memcpy(arr, (char *)p, sizeof *p);
or
memcpy((void *)arr, (void *)p, sizeof *p);

Do I need the cast here ? Or the way I am trying to do it is correct ?
I have not tested the code, so I am not sure of it either.

That "someone" is blowing smoke or else using a language other than C.
Your form is just fine.
 
G

Greg Barron

Your informant is wrong. No such casts are necessary in C.

To be more specific, no casts are required to convert any pointer type to
or from void *.

Cheers,
 
R

Richard Bos

The linux manpage for memcpy(3) gives me the following prototype of
memcpy(3):
#include <string.h>
void *memcpy(void *dest, const void *src, size_t n);
memcpy(arr, p, sizeof *p);

Someone tells me -- this is an incorrect usage, you either need to do
memcpy(arr, (char *)p, sizeof *p);
or
memcpy((void *)arr, (void *)p, sizeof *p);

That someone is wrong. Unlike, for example, C++, the C language does not
require the casts. IMO, this is a point where C is clearly superior.

Richard
 
M

Martin Dickopp

Greg Barron said:
To be more specific, no casts are required to convert any pointer type
to or from void *.

That only applies to pointers to objects, but not to function pointers.
The latter cannot be converted to `void *' (or vice versa) at all.

Martin
 
P

pete

Martin said:
That only applies to pointers to objects,
but not to function pointers.
The latter cannot be converted to `void *' (or vice versa) at all.

A cast is required when converting from (const void *) to (void *).
 
K

Kelsey Bjarnason

[snips]

A cast is required when converting from (const void *) to (void *).

This should, in all likelihood, simply not be done in the first place. :)
 
B

Ben Pfaff

That someone is wrong. Unlike, for example, C++, the C language does not
require the casts. IMO, this is a point where C is clearly superior.

As I read the C++ standard, C++ requires a cast to convert from
void * to pointer-to-object type, but not to convert from
pointer-to-object type to void *. I am willing to be corrected
on this point.
 
P

Peter Pichler

Richard Bos said:
Unlike, for example, C++, the C language does not
require the casts. IMO, this is a point where C is clearly superior.

Another one is readability ;-)
 
M

Michael Wojcik

This should, in all likelihood, simply not be done in the first place. :)

There are times when it is (IMO) appropriate. I often find myself
dealing with APIs supplied by another developer that are not const-
correct - that is, they don't declare object-pointer parameters to
data they do not change as const. When I wrap such a function in one
of my own, mine will be const-correct. At some point, then, I may
have to pass a pointer to a const object as a pointer to a non-const
object. That's going to require a const-removing cast somewhere.

(The alternatives that come to mind are copying the data into a new
area and passing a non-const pointer to it, and getting the API owner
to fix his API. The former is obviously less than optimal. The
latter is preferable but not always achievable in a reasonable
timeframe.)

--
Michael Wojcik (e-mail address removed)

Be sure to push the button of the bottom, and push the button of the
settlement page indicated next only once, there is fear of the bottom
rhinoceros multiplex lesson money. -- Sukebe Net
 
A

Amarendra GODBOLE

Ben Pfaff said:
Your informant is wrong. No such casts are necessary in C.

Thanks all of you. All the replies have made my stand strong, and I
can prove my point now. But this cannot be end without a small joke...

I wrote a code snippet for my colleague: (the ``someone'' in my
previous post.) :)

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(void)
{
char arr[20];
typedef struct foo_ {
int i;
char c;
float f;
} foo;
foo *fptr;
foo *fptr1;

/* Okay, in real life we need to check the return value of
malloc() */
fptr = malloc(sizeof *fptr);
fptr->i = 21;
fptr->c = 'A';
fptr->f = 16.45;

memcpy(arr, fptr, sizeof *fptr);
fptr1 = (foo *)arr;

printf("Array contains %i, %c, %f\n", fptr1->i, fptr1->c,
fptr1->f);
free(fptr);

return 0;
}

I do get correct values printed out. Even after this, my colleague
told me that it has worked here because foo is a simple stucture, and
it might not work in complicated structures (!). Never heard that C --
makes a distinction between simple and complex structures !! ;)

Thanks once again.

Cheers,
Amarendra
 
M

Martien Verbruggen

I wrote a code snippet for my colleague: (the ``someone'' in my
previous post.) :)
foo *fptr;
foo *fptr1;
memcpy(arr, fptr, sizeof *fptr);
fptr1 = (foo *)arr;

You also don't need, and shouldn't use, this cast.
I do get correct values printed out. Even after this, my colleague
told me that it has worked here because foo is a simple stucture, and
it might not work in complicated structures (!). Never heard that C --
makes a distinction between simple and complex structures !! ;)

Your collegue is still wrong. If he means that you can't simply use
memcpy() to make a 'deep' copy of a structure that has pointers in iti
(which could be one interpretation of 'complicated' structures),
he/she is right, but that won't be fixed with a cast.

The point is simply that casts are not necessary in memcpy() (or
anywhere else where pointers need to be converted to void * or from
void *). The complexity of whatever is being pointed to does not
change that in any way. Maybe your collegue could explain what
"complicated structures" are?

Martien
 
C

CBFalconer

Amarendra said:
Ben Pfaff said:
Your informant is wrong. No such casts are necessary in C.

Thanks all of you. All the replies have made my stand strong, and I
can prove my point now. But this cannot be end without a small joke...

I wrote a code snippet for my colleague: (the ``someone'' in my
previous post.) :)

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(void)
{
char arr[20];
typedef struct foo_ {
int i;
char c;
float f;
} foo;
foo *fptr;
foo *fptr1;

/* Okay, in real life we need to check the return value of
malloc() */
fptr = malloc(sizeof *fptr);
fptr->i = 21;
fptr->c = 'A';
fptr->f = 16.45;

memcpy(arr, fptr, sizeof *fptr);
fptr1 = (foo *)arr;

printf("Array contains %i, %c, %f\n", fptr1->i, fptr1->c,
fptr1->f);
free(fptr);

return 0;
}

I do get correct values printed out. Even after this, my colleague
told me that it has worked here because foo is a simple stucture, and
it might not work in complicated structures (!). Never heard that C --
makes a distinction between simple and complex structures !! ;)

Wrong answer. 'Working' here actually depends on the alignment of
arr, over which you have no direct control. There are several
illegalities in your code snippet, especially including the
assignment to fptr1 and the cast involved. Ugh.
 
C

Christian Bau

CBFalconer said:
Wrong answer. 'Working' here actually depends on the alignment of
arr, over which you have no direct control. There are several
illegalities in your code snippet, especially including the
assignment to fptr1 and the cast involved. Ugh.

Many people who are not deterred by the plain ugliness and the fact that
there is undefined behavior (which means even if it "works" today, it
can fail if you compile it again with the next compiler version, with an
optimising compiler, with a different compiler, on a different
architecture), might be deterred by the fact that using unaligned
pointer might easily make your code run fifty times slower than it
could.
 
A

Amarendra GODBOLE

memcpy(arr, fptr, sizeof *fptr);
Wrong answer. 'Working' here actually depends on the alignment of
arr, over which you have no direct control. There are several
illegalities in your code snippet, especially including the
assignment to fptr1 and the cast involved. Ugh.

Hmmm...yes, right you are. How do I get the values back then ? Will
you kindly point out the other illegalities too ? Thanks in advance.

Cheers,
Amarendra
 
P

pete

Amarendra said:
Hmmm...yes, right you are. How do I get the values back then ? Will
you kindly point out the other illegalities too ? Thanks in advance.

The size issue can be addressed by using the sizeof result
from the structure, to allocate the array.
The alignment issue can be addressed by a union,
as in K&R2 Section 8.7, Example-A Storage Allocator.

/* BEGIN memcast.c */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(void)
{
struct foo {
int i;
char c;
float f;
};
union {
char arr[sizeof(struct foo)];
struct foo align;
} align;
struct foo struct1;
struct foo *fptr1;

struct1.i = 21;
struct1.c = 'A';
struct1.f = 16.45f;
memcpy(align.arr, &struct1, sizeof struct1);
fptr1 = (struct foo *)align.arr;
printf("Array contains %i, %c, %f\n",
fptr1 -> i, fptr1 -> c, fptr1 -> f);
return 0;
}

/* END memcast.c */
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,534
Members
45,008
Latest member
Rahul737

Latest Threads

Top