views:

1021

answers:

7

I've asked a similar question on structs here but I'm trying to figure out how C handles things like assigning variables and why it isn't allowed to assign them to eachother if they are functionally the same.

Lets say I have two arrays:

int x[10];  
int y[10];

Why won't x = y compile? If they are both the same "signature" like that, then shouldn't you be able to assign them back and forth?

Can I declare these in a way that would allow me to do that in C? It makes sense to me that you would be able to, but maybe there is a way that this can be done? Typedefs for structs seemed to be the solution, would it be the same for array declaration and assignment?

I appreciate your guys help, I'm new to Stackoverflow but it has been a really good resource for me so far!

+2  A: 

When you declare those arrays, the compiler reserves space for 10 ints. When you assign one "array" (which is just a pointer to the first element), you'd just copy the pointers, not the contents.
For copying, there are functions like memcpy, if you want to assign x (or y) to something, you'd have to assign it to a int*.

tstenner
+10  A: 

The name of an array is actually the address of the first element of that array.

The example code you provide here is attempting to assign to something which is not an l-value.

It's like doing this;

int
  x[10],
  y[10];

&x[0] = &y[0];

You can do with structs what you're getting at here;

struct data
  a,
  b;

a = b;

And in fact if struct data is declared as;

struct data
{
  int
    x[10];
};

then you'd be doing exactly what you're trying to do here!

But you can't do it directly with arrays. Use memcpy().

Blank Xavier
extra woot, 650!
Blank Xavier
Quick, vote him up so he goes "Wowzer! +30! Why is my rep still at 790?"
tstenner
I would *never* say "wowzer" :-)
Blank Xavier
Where can I mod you down? :-)
Blank Xavier
That code still doesn't do what he was *wanting* it to do though, does it? Perhaps I'm wrong, but I got the impression he was hoping to copy the contents of the y array into x.
T.E.D.
True. Fortunately, lots of other replies have indicated memcpy() is the correct choice. I'll add it in...
Blank Xavier
A: 

In order to assign arrays you will have to assign the values inside the array.

ie. x=y is equivalent to

for(int i = 0; i < 10 < ++i)
{
x[i] = y[i];
}
aJ
x=y is a compiler error.
Naveen
thats why I am giving the equivalent!
aJ
it gives the impression that x=y is a valid statement
Naveen
Actually in the OP its already mentioned that x=y doesn't compile.
aJ
x=y being impossible for arrays is the entire context for this question, Naveen.
Chuck
A: 

When saying "int x[10]" is saying, "reserve some room for 10 integers and pass me a pointer to the location". So for the copy to make sense you'd need to operate on the memory pointed by, rather than 'the name of the memory location'.

So for copying here you'd use a for loop or memcpy().

amo-ej1
+1  A: 

You have to look at what the variables represent. In your code, you now have two chunks of memory, both big enough to hold 10 integers.

Now, x[0] is the first chunks 0th integer, and y[0] is the seconds. But x itself is a pointer to the first element. Likewise, y is a pointer to the second chunk.

So saying x = y would try to assign x to now be pointing at y's chunk. And x's array is a lost forever. If you dynamically allocated these 2 chunks with malloc, you would be able to say "x = y", setting x to point to the second dynamically allocated chunk, but losing x's chunk forever (memory leak).

This error is the compiler preventing you from doing so. To copy each element, you have to loop through the arrays:

for (int i = 0; i < 10; ++i)
{
    x[i] = y[i];
}
GMan
To copy every element, you need to use memcpy(), not a loop!
Blank Xavier
What's the difference, Blank?
Chuck
I suppose in C you should use memcpy. I mostly use C++, and doing bit-wise copies is obviously a terrible idea.
GMan
A: 

Some messages state the name of an array yields the address of its first element. It's not always true:

#include <stdio.h>

int
main(void)
{
  int array[10];

  /*
   * Print the size of the whole array then the size of a pointer to the
   * first element.
   */
  printf("%u %u\n", (unsigned int)sizeof array, (unsigned int)sizeof &array[0]);

  /*
   * You can take the address of array, which gives you a pointer to the whole
   * array. The difference between ``pointer to array'' and ``pointer to the
   * first element of the array'' matters when you're doing pointer arithmetic.
   */
  printf("%p %p\n", (void*)(&array + 1), (void*)(array + 1));

  return 0;
}

Output:

40 4
0xbfbf2ca4 0xbfbf2c80
Bastien Léonard
A: 

I've used C compilers where that would compile just fine...and when run the code would make x point to y's array.

You see, in C the name of an array is a pointer that points to the start of the array. In fact, arrays and pointers are essentially interchangable. You can take any pointer and index it like an array.

Back when C was being developed in the early 70's, it was meant for relatively small programs that were barely above assembly language in abstraction. In that environment, it was damn handy to be able to easily go back and forth between array indexing and pointer math. Copying whole arrays of data, on the other hand, was a very expensive thing do do, and hardly something to be encouraged or abstracted away from the user.

Yes, in these modern times it would make way more sense to have the name of the array be shorthand for "the whole array", rather than for "a ponter to the front of the array". However, C wasn't designed in these modern times. If you want a language that was, try Ada. x := y there does exactly what you would expect; it copies one array's contents to the other.

T.E.D.