Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does C copy the element every time you access an array?

Tags:

c++

arrays

c

C can't return references unlike C++. Does that mean if you access A[i] it will copy the element in evaluating the expression?

For example if A is an array of 10 ints, does A[5]+=1; only increment the temporary copy built when evaluating A[5], unlike C++'s vector which will increment the actual sixth element itself?

like image 848
Aaa Bbb Avatar asked Jul 23 '17 10:07

Aaa Bbb


3 Answers

C always copies an element when reading from an array with A[i], that is, when the expression A[i] is an “rvalue”. However, when considering writes, C has a notion of “lvalue” expressions, which are essentially a restricted subset of expression syntax that are allowed to appear as the destination of an assignment:

X    = Y
*X   = Y
X[i] = Y
X.n  = Y

In these cases, the “expressions” *X, X[i], and X.n don’t actually evaluate to values—they have the same syntax as expressions, for convenience, but not the same semantics. You can think of these as something more like the following:

memcpy(&X,    &Y, sizeof(Y));
memcpy(&*X,   &Y, sizeof(Y));
memcpy(&X[i], &Y, sizeof(Y));
memcpy(&X.n,  &Y, sizeof(Y));

Or, alternatively, think of C as having multiple different assignment operators:

_    = _  // direct assignment
*_   = _  // indirect assignment
_[_] = _  // special case of indirect assignment
_._  = _  // special case of indirect assignment

Either way, an assignment such as A[5] += 1 will increment the value of the sixth element of A in place, just as you would expect, which you can verify like so:

int A[1] = { 1 };
A[0] += 5;
printf("%d\n", A[0]);  // 6
like image 175
Jon Purdy Avatar answered Oct 19 '22 15:10

Jon Purdy


C has a concept called an 'lvalue' which is sort-of like a reference. It's not a type (not part of the type system), but certain C expressions are 'lvalues', and only such expressions can be the left operand of an assignment (including an op-assign) or an increment/decrement.

Since C has no operator overloading, there's no need to have a distinction in the type system as there's never any need to declare things as rvalues vs lvalues. It was the desire to add operator overloading in C++ that lead to the introduction of reference types to make the rvalue/lvalue distinction clear for overloaded operators.

like image 12
Chris Dodd Avatar answered Oct 24 '22 07:10

Chris Dodd


If that was true, you would be unable to modify arrays at all and the expression A[5]+=1; would have no effect!

On the opposite, when you pass a scalar argument to a function, it behaves like a copy because it is not modified upon return. But an array, in fact passed as a pointer, is not copied (that would be unbearably costly) and can be different upon return.

like image 5
Yves Daoust Avatar answered Oct 24 '22 06:10

Yves Daoust