Help with reading this line of code -- thanks!

A

almurph

Hi,

Can anyone help me interpret this line of code (I'm a C# man, my C is
a bit rusty):


memcpy((char*)A, (char*)A->SomeArray[MaxVal], sizeof(ARec));


I get the "A->SomeArray[MaxVal]" bit - its the rest that's throwing
me. I know that memcpy(A, B, n) copies B into A (more or less) but its
the "(char*) stuff that's confusing me.

Would appreciate any comments/suggestions/insight that you can give
me.

Thanks,
Al.
 
K

Kojak

Le Thu, 26 Feb 2009 05:16:02 -0800 (PST),
(e-mail address removed) a écrit :
memcpy((char*)A, (char*)A->SomeArray[MaxVal], sizeof(ARec));

I get the "A->SomeArray[MaxVal]" bit - its the rest that's
throwing me. I know that memcpy(A, B, n) copies B into A (more or
less) but its the "(char*) stuff that's confusing me.

It's just a cast operator. '(char *)expr' meens that what you get
with 'expr' will be treated as a 'pointer to a char'.
 
B

Bartc

Hi,

Can anyone help me interpret this line of code (I'm a C# man, my C is
a bit rusty):


memcpy((char*)A, (char*)A->SomeArray[MaxVal], sizeof(ARec));


I get the "A->SomeArray[MaxVal]" bit - its the rest that's throwing
me. I know that memcpy(A, B, n) copies B into A (more or less) but its
the "(char*) stuff that's confusing me.

(char*)X means that X is interpreted as a pointer to char, which is what
memcpy expects. And could probably be omitted.

But if it is being used, I think the second (char*) should apply to the
whole second argument, not just the A. I might be wrong though otherwise it
might not compile.

The code overwrites the struct pointed to by A, with a completely new
struct. And hopefully SomeArray will be an array of pointers to the same
struct (or a pointer to such an array; you can't tell but can only deduce
from your code fragment).
 
B

Boon

Bartc said:
(char*)X means that X is interpreted as a pointer to char,
which is what memcpy expects.

Actually memcpy expects pointers to void.

4.11.2.1 The memcpy function

Synopsis

#include <string.h>
void *memcpy(void *s1, const void *s2, size_t n);

Description

The memcpy function copies n characters from the object pointed to
by s2 into the object pointed to by s1 . If copying takes place
between objects that overlap, the behavior is undefined.

Returns

The memcpy function returns the value of s1.
 
B

Ben Bacarisse

Can anyone help me interpret this line of code (I'm a C# man, my C is
a bit rusty):

memcpy((char*)A, (char*)A->SomeArray[MaxVal], sizeof(ARec));

I get the "A->SomeArray[MaxVal]" bit - its the rest that's throwing
me. I know that memcpy(A, B, n) copies B into A (more or less) but its
the "(char*) stuff that's confusing me.

They are probably pointless. Remove them and check that the program
compiles with no extra errors or warnings (make sure you are no
accidentally compiling the code using a C++ compiler).

It helps, with this sort of question, to know the types of the things
involved. Without that I can't be sure that the casts are doing
nothing but if you understand the code except for the casts you almost
certainly understand the code.
 
B

Ben Bacarisse

Bartc said:
Hi,

Can anyone help me interpret this line of code (I'm a C# man, my C is
a bit rusty):


memcpy((char*)A, (char*)A->SomeArray[MaxVal], sizeof(ARec));


I get the "A->SomeArray[MaxVal]" bit - its the rest that's throwing
me. I know that memcpy(A, B, n) copies B into A (more or less) but its
the "(char*) stuff that's confusing me.

(char*)X means that X is interpreted as a pointer to char, which is
what memcpy expects.

It used to but that was pre C99! memcpy now takes void *.
And could probably be omitted.

But if it is being used, I think the second (char*) should apply to
the whole second argument, not just the A. I might be wrong though
otherwise it might not compile.

All postfix operators (-> and [] in this case) bind more tightly than
all prefix operators so, yes, the cast applies to A->SomeArray[MaxVal].
 
B

Ben Bacarisse

pete said:
Ben said:
Bartc said:
Hi,

Can anyone help me interpret this line of code (I'm a C# man, my C is
a bit rusty):


memcpy((char*)A, (char*)A->SomeArray[MaxVal], sizeof(ARec));


I get the "A->SomeArray[MaxVal]" bit - its the rest that's throwing
me. I know that memcpy(A, B, n) copies B into A (more or less) but its
the "(char*) stuff that's confusing me.
(char*)X means that X is interpreted as a pointer to char, which is
what memcpy expects.

It used to but that was pre C99!

By at least ten years.

Yes a typo. Of course I made the only typo that looks like I might
have meant it!. If future, I think I'll write "pre-standard C".
 
K

Keith Thompson

Ben Bacarisse said:
Bartc said:
Can anyone help me interpret this line of code (I'm a C# man, my C is
a bit rusty):


memcpy((char*)A, (char*)A->SomeArray[MaxVal], sizeof(ARec));


I get the "A->SomeArray[MaxVal]" bit - its the rest that's throwing
me. I know that memcpy(A, B, n) copies B into A (more or less) but its
the "(char*) stuff that's confusing me.

(char*)X means that X is interpreted as a pointer to char, which is
what memcpy expects.

It used to but that was pre C99! memcpy now takes void *.
[...]

Actually that was pre C89. The code might have been written for a K&R
compiler -- or it might have been written by someone who didn't know
any better. I doubt that you could even find an implementation where
memcpy() takes char* arguments. (Yes, I'm sure someone could; I was
generalizing.)

Since conversion from any pointer-to-object type to void* is implicit
you can drop the casts:

memcpy(A, A->SomeArray[MaxVal], sizeof(ARec));

It would be helpful to see the relevant declarations. Since it's used
with the "->" operator, we know A is a pointer to a struct (or a
union). This structure contains an array called SomeArray (or
SomeArray could be a pointer to the first element of an array; in fact
it probably is), and the call copies the value of an element of that
array into the structure pointed to by A itself. This is going to
clobber A->SomeArray, but since the arguments are evaluated before the
call, and therefore before the copying takes place, that shouldn't be
a problem.

ARec is probably a typedef for a structure type, and it's probably the
type that A points to. And since structures can be assigned, the
memcpy could probably be changed to:

*A = A->SomeArray[MaxVal];

But without seeing the declarations, it's hard to be certain.
 
P

Phil Carmody

Kojak said:
Le Thu, 26 Feb 2009 05:16:02 -0800 (PST),
(e-mail address removed) a écrit :
memcpy((char*)A, (char*)A->SomeArray[MaxVal], sizeof(ARec));

I get the "A->SomeArray[MaxVal]" bit - its the rest that's
throwing me. I know that memcpy(A, B, n) copies B into A (more or
less) but its the "(char*) stuff that's confusing me.

It's just a cast operator. '(char *)expr' meens that what you get
with 'expr' will be treated as a 'pointer to a char'.

Except when it doesn't.

size_t a = sizeof (char*)*p;

Phil
 
K

Keith Thompson

Anthony Fremont said:
Keith Thompson wrote:


I had a run-in with gcc today. It didn't want me taking the difference
between a char* and a void*. It refused to implicitly convert anything.
When I cast the void* to char*, it was happy to do the pointer subtraction.
After pondering on it a minute, I'm of the opinion that it is completely
appropriate behavior.

Yes, it sounds like gcc gets this right. The implicit conversion
occurs on assignment, argument passing, and initialization, not in all
possible contexts.

(gcc does let you subtract a void* from a void*, which is a permitted
extension but IMHO a bad idea.)
 
K

Keith Thompson

Anthony Fremont said:
Ben Bacarisse wrote:
....

Or using Linux gcc to compile a .C (capital) file. Ultraedit created a file
with a big C for the extension and gcc was griping about code that I had
just cut and pasted from a program that compiled without warning. :)

That's just an instance of using a C++ compiler. gcc is actually a
collection of compilers; it invokes the C compiler for a file with a
".c" suffix, a C++ compiler for a file with a ".C" or ".cpp" suffix
(there may be others), and so forth.
 
B

Ben Bacarisse

Phil Carmody said:
Kojak said:
Le Thu, 26 Feb 2009 05:16:02 -0800 (PST),
(e-mail address removed) a écrit :
memcpy((char*)A, (char*)A->SomeArray[MaxVal], sizeof(ARec));

I get the "A->SomeArray[MaxVal]" bit - its the rest that's
throwing me. I know that memcpy(A, B, n) copies B into A (more or
less) but its the "(char*) stuff that's confusing me.

It's just a cast operator. '(char *)expr' meens that what you get
with 'expr' will be treated as a 'pointer to a char'.

Except when it doesn't.

size_t a = sizeof (char*)*p;

There is not cast operator here. The "thing" that follows sizeof in
this syntax is a "type name" in brackets not a cast operator.
 
C

CBFalconer

Can anyone help me interpret this line of code (I'm a C# man, my
C is a bit rusty):

memcpy((char*)A, (char*)A->SomeArray[MaxVal], sizeof(ARec));

I get the "A->SomeArray[MaxVal]" bit - its the rest that's
throwing me. I know that memcpy(A, B, n) copies B into A (more
or less) but its the "(char*) stuff that's confusing me.

Eliminate the (char*). Totally unnecessary, and it prevents error
messages. Notice that memcpy takes void* parameters, and there is
no need to cast them. However notice the restrict word, which
guarantees that the two parameters are completely independent. It
is highly possible that you are making an illegal call.

7.21.2.1 The memcpy function
Synopsis
[#1]
#include <string.h>
void *memcpy(void * restrict s1,
const void * restrict s2,
size_t n);

In general casts in C source are bad, preventing error messages,
and unnecessary. The exception is variadic function parameters,
such as printf.
 
P

Phil Carmody

Ben Bacarisse said:
Phil Carmody said:
Kojak said:
Le Thu, 26 Feb 2009 05:16:02 -0800 (PST),
(e-mail address removed) a écrit :

memcpy((char*)A, (char*)A->SomeArray[MaxVal], sizeof(ARec));

I get the "A->SomeArray[MaxVal]" bit - its the rest that's
throwing me. I know that memcpy(A, B, n) copies B into A (more or
less) but its the "(char*) stuff that's confusing me.

It's just a cast operator. '(char *)expr' meens that what you get
with 'expr' will be treated as a 'pointer to a char'.

Except when it doesn't.

size_t a = sizeof (char*)*p;

There is not cast operator here.

Yes, that's why said it wasn't. Keep up.
The "thing" that follows sizeof in
this syntax is a "type name" in brackets not a cast operator.

Erm, I know that. Whatever made you think I didn't?

Phil
 
G

Guest

CBFalconer said:
Can anyone help me interpret this line of code (I'm a C# man, my
C is a bit rusty):
  memcpy((char*)A, (char*)A->SomeArray[MaxVal], sizeof(ARec));
I get the "A->SomeArray[MaxVal]" bit - its the rest that's
throwing me. I know that memcpy(A, B, n) copies B into A (more
or less) but its the "(char*) stuff that's confusing me.
Eliminate the (char*).  Totally unnecessary, and it prevents error
messages.  Notice that memcpy takes void* parameters, and there is
no need to cast them.

All this has been mentioned in other articles posted long before
yours.

I just re-read the entire thread I can't see any other post that
explicitly says "prevents error messages"
<deploy language lawyer repellant>


<snip>
 
K

Kojak

Le Thu, 26 Feb 2009 21:47:49 +0200,
Phil Carmody a écrit :
Except when it doesn't.

size_t a = sizeof (char*)*p;

Ouch !

Visually speaking, say yes. But, let me rewrite the line:

size_t a = (sizeof (char *)) * (p);

there is no actualy expr after (char *). ;-)
 
B

Ben Bacarisse

Phil Carmody said:
Ben Bacarisse said:
Phil Carmody said:
Le Thu, 26 Feb 2009 05:16:02 -0800 (PST),
(e-mail address removed) a écrit :

memcpy((char*)A, (char*)A->SomeArray[MaxVal], sizeof(ARec));

I get the "A->SomeArray[MaxVal]" bit - its the rest that's
throwing me. I know that memcpy(A, B, n) copies B into A (more or
less) but its the "(char*) stuff that's confusing me.

It's just a cast operator. '(char *)expr' meens that what you get
with 'expr' will be treated as a 'pointer to a char'.

Except when it doesn't.

size_t a = sizeof (char*)*p;

There is not cast operator here.

Yes, that's why said it wasn't. Keep up.
OK.
The "thing" that follows sizeof in
this syntax is a "type name" in brackets not a cast operator.

Erm, I know that. Whatever made you think I didn't?

The rather blank style, sorry. If you had said "(char *)expr is not
always a cast expression", I think it would have made your point more
clearly. Even if you'd just cut off the preceding "It's just a cast
operator." I think there would have been less confusion (to me). I
thought you were objecting to the whole paragraph whereas you were
only objecting to the second sentence taken on it own without the
first.

There is a real problem here. I am not keen on the idea that every
given text must be made up sentences that are entirely true even when
read on their own:

Q: I am confused by this code: *p == 1. I understand the == 1 part
but what does the * mean?

A: It is the indirection operator. *p gives you the "thing" p points
to.

New voice: Except when it does not (with examples).

Does that really help? Obviously you think it does, but I don't think
there is a real risk of confusion. Part of my confusion was caused by
the fact that I did not think you could be saying "that sequence of
characters can mean other things in other contexts". That is too
common a problem to be raising (I thought).

There is a lot of noise of on c.l.c and I have just added to it by
misunderstanding your remark. This is my fault, and I will try to
read what everyone writes more carefully in future. But we can all
help cut down the noise by trying to avoid being misunderstood.
 
P

Phil Carmody

Kojak said:
Le Thu, 26 Feb 2009 21:47:49 +0200,
Phil Carmody a écrit :


Ouch !

Thank you. That's the nicest thing anyone's ever said when
presented with such a line of code in such a context.

Phil
 

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,996
Messages
2,570,238
Members
46,826
Latest member
robinsontor

Latest Threads

Top