2009-09-22 17:24:43 8 Comments
What is decaying of an array? Is there any relation to array pointers?
Related Questions
Sponsored Content
34 Answered Questions
[SOLVED] For-each over an array in JavaScript?
- 2012-02-17 13:51:48
- Dante1986
- 3925094 View
- 4462 Score
- 34 Answer
- Tags: javascript arrays loops foreach iteration
23 Answered Questions
[SOLVED] What is the "-->" operator in C++?
- 2009-10-29 06:57:45
- GManNickG
- 753423 View
- 8611 Score
- 23 Answer
- Tags: c++ c operators code-formatting standards-compliance
25 Answered Questions
[SOLVED] Why is processing a sorted array faster than processing an unsorted array?
- 2012-06-27 13:51:36
- GManNickG
- 1430540 View
- 23711 Score
- 25 Answer
- Tags: java c++ performance optimization branch-prediction
89 Answered Questions
[SOLVED] How do I remove a particular element from an array in JavaScript?
- 2011-04-23 22:17:18
- Walker
- 6169321 View
- 7695 Score
- 89 Answer
- Tags: javascript arrays
34 Answered Questions
[SOLVED] Create ArrayList from array
- 2008-10-01 14:38:32
- Ron Tuffin
- 1441447 View
- 3451 Score
- 34 Answer
- Tags: java arrays arraylist type-conversion
37 Answered Questions
47 Answered Questions
[SOLVED] How do I check if an array includes a value in JavaScript?
- 2008-10-25 22:14:40
- brad
- 2419882 View
- 3798 Score
- 47 Answer
- Tags: javascript arrays algorithm time-complexity javascript-objects
16 Answered Questions
[SOLVED] How to insert an item into an array at a specific index (JavaScript)?
- 2009-02-25 14:29:30
- tags2k
- 1726371 View
- 2723 Score
- 16 Answer
- Tags: javascript jquery arrays insert
30 Answered Questions
[SOLVED] How to append something to an array?
- 2008-12-09 00:20:05
- interstar
- 3020239 View
- 2895 Score
- 30 Answer
- Tags: javascript arrays append
18 Answered Questions
[SOLVED] With arrays, why is it the case that a[5] == 5[a]?
- 2008-12-19 17:01:33
- Dinah
- 95279 View
- 1574 Score
- 18 Answer
- Tags: c arrays pointers pointer-arithmetic
9 comments
@Chef Gladiator 2019-11-09 07:44:18
I might be so bold to think there are four (4) ways to pass an array as the function argument. Also here is the short but working code for your perusal.
I might also think this shows the superiority of C++ vs C. At least in reference (pun intended) of passing an array by reference.
Of course there are extremely strict projects with no heap allocation, no exceptions and no std:: lib. C++ native array handling is mission critical language feature, one might say.
@Josh Kelley 2009-09-22 17:35:45
Array decaying means that, when an array is passed as a parameter to a function, it's treated identically to ("decays to") a pointer.
There are two complications or exceptions to the above.
First, when dealing with multidimensional arrays in C and C++, only the first dimension is lost. This is because arrays are layed out contiguously in memory, so the compiler must know all but the first dimension to be able to calculate offsets into that block of memory.
Second, in C++, you can use templates to deduce the size of arrays. Microsoft uses this for the C++ versions of Secure CRT functions like strcpy_s, and you can use a similar trick to reliably get the number of elements in an array.
@M.M 2015-03-17 03:44:47
decay happens in many other situations, not just passing an array to a function.
@einpoklum - reinstate Monica 2018-03-13 09:59:08
tl;dr: When you use an array you've define, you'll actually be using a pointer to its first element.
Thus:
arr[idx]
you're really just saying*(arr + idx)
.Sort-of exceptions to this rule:
struct
.sizeof()
gives the size taken up by the array, not the size of a pointer.@system PAUSE 2009-09-22 17:31:36
Arrays are basically the same as pointers in C/C++, but not quite. Once you convert an array:
into a pointer (which works without casting, and therefore can happen unexpectedly in some cases):
you lose the ability of the
sizeof
operator to count elements in the array:This lost ability is referred to as "decay".
For more details, check out this article about array decay.
@John Bode 2009-09-22 19:39:54
Arrays are not basically the same as pointers; they are completely different animals. In most contexts, an array can be treated as though it were a pointer, and a pointer can be treated as though it were an array, but that's as close as they get.
@system PAUSE 2009-09-23 15:17:59
@John, please pardon my imprecise language. I was trying to get to the answer without getting bogged down in a lengthy backstory, and "basically...but not quite" is as good an explanation as I ever got in college. I'm sure anyone who's interested can get a more accurate picture from your upvoted comment.
@M.M 2015-03-17 03:39:13
"works without casting" means the same as "happen implicitly" when talking about type conversions
@phoebus 2009-09-22 17:29:02
It's said that arrays "decay" into pointers. A C++ array declared as
int numbers [5]
cannot be re-pointed, i.e. you can't saynumbers = 0x5a5aff23
. More importantly the term decay signifies loss of type and dimension;numbers
decay intoint*
by losing the dimension information (count 5) and the type is notint [5]
any more. Look here for cases where the decay doesn't happen.If you're passing an array by value, what you're really doing is copying a pointer - a pointer to the array's first element is copied to the parameter (whose type should also be a pointer the array element's type). This works due to array's decaying nature; once decayed,
sizeof
no longer gives the complete array's size, because it essentially becomes a pointer. This is why it's preferred (among other reasons) to pass by reference or pointer.Three ways to pass in an array1:
The last two will give proper
sizeof
info, while the first one won't since the array argument has decayed to be assigned to the parameter.1 The constant U should be known at compile-time.
@rlbond 2009-09-22 18:54:33
How is the first passing by value?
@John Bode 2009-09-22 19:35:06
by_value is passing a pointer to the first element of the array; in the context of function parameters,
T a[]
is identical toT *a
. by_pointer is passing the same thing, except the pointer value is now qualifiedconst
. If you want to pass a pointer to the array (as opposed to a pointer to the first element of the array), the syntax isT (*array)[U]
.@Pavel Minaev 2009-09-22 19:39:26
"with an explicit pointer to that array" - this is incorrect. If
a
is an array ofchar
, thena
is of typechar[N]
, and will decay tochar*
; but&a
is of typechar(*)[N]
, and will not decay.@Johannes Schaub - litb 2009-09-22 19:41:18
oO the first and second declare the same function (the top-level const right before
array
is ignored). In C99, the toplevel const can also be specified for the first case - you can dovoid by_value(const T array[const]);
- but this isn't significant in determining what function is declared. In any case, this answer probably should mention thatvoid f(int array[N]);
for any N > 0 is the same asvoid f(int *array);
.@phoebus 2009-09-22 20:12:51
@rlbond: It's idiomatically "by value", not literally.
@phoebus 2009-09-22 20:35:51
@litb It's just meant to show some varying syntactic sugar there.
@fredoverflow 2014-06-05 10:37:41
In the third example, why would you even use
sizeof
when you already know that the array hasU
elements? :)@Lightness Races with Monica 2014-06-05 10:40:27
@FredOverflow: So if
U
changes you don't have to remember to change it in two places, or risk silent bugs... Autonomy!@fredoverflow 2014-06-05 10:41:34
@LightnessRacesinOrbit If
U
changes its value or its name?@Lightness Races with Monica 2014-06-05 10:44:24
@FredOverflow: Notice that these examples are not templates;
U
is presumably a stand-in for an integer literal, not a template parameter. Thus, the answer to your question, is "its value".@Deduplicator 2014-06-09 14:15:44
Array decay happens on function call, but also anywhere else an array is used but for
sizeof
,&
,decltype
,alignof
,alignas
.@juanchopanza 2015-09-20 13:38:53
"If you're passing an array by value, what you're really doing is copying a pointer" That makes no sense, because arrays can''t be passed by value, period.
@L. F. 2019-05-14 13:19:54
There are actually six ways to pass in an array: the three non-mutating versions, which the answer already mentioned, and their mutating counterparts:
(T* arr)
,T (*arr)[U]
, andT (&arr)[U]
.@John Bode 2009-09-22 20:21:27
"Decay" refers to the implicit conversion of an expression from an array type to a pointer type. In most contexts, when the compiler sees an array expression it converts the type of the expression from "N-element array of T" to "pointer to T" and sets the value of the expression to the address of the first element of the array. The exceptions to this rule are when an array is an operand of either the
sizeof
or&
operators, or the array is a string literal being used as an initializer in a declaration.Assume the following code:
The expression
a
is of type "80-element array of char" and the expression "This is a test" is of type "16-element array of char" (in C; in C++ string literals are arrays of const char). However, in the call tostrcpy()
, neither expression is an operand ofsizeof
or&
, so their types are implicitly converted to "pointer to char", and their values are set to the address of the first element in each. Whatstrcpy()
receives are not arrays, but pointers, as seen in its prototype:This is not the same thing as an array pointer. For example:
Both
ptr_to_first_element
andptr_to_array
have the same value; the base address of a. However, they are different types and are treated differently, as shown below:Remember that the expression
a[i]
is interpreted as*(a+i)
(which only works if the array type is converted to a pointer type), so botha[i]
andptr_to_first_element[i]
work the same. The expression(*ptr_to_array)[i]
is interpreted as*(*a+i)
. The expressions*ptr_to_array[i]
andptr_to_array[i]
may lead to compiler warnings or errors depending on the context; they'll definitely do the wrong thing if you're expecting them to evaluate toa[i]
.Again, when an array is an operand of
sizeof
, it's not converted to a pointer type.ptr_to_first_element
is a simple pointer to char.@chux - Reinstate Monica 2013-12-07 17:47:44
Isn't
"This is a test" is of type "16-element array of char"
a"15-element array of char"
? (length 14 + 1 for \0)@Michael Burr 2009-09-22 19:27:11
Here's what the standard says (C99 6.3.2.1/3 - Other operands - Lvalues, arrays, and function designators):
This means that pretty much anytime the array name is used in an expression, it is automatically converted to a pointer to the 1st item in the array.
Note that function names act in a similar way, but function pointers are used far less and in a much more specialized way that it doesn't cause nearly as much confusion as the automatic conversion of array names to pointers.
The C++ standard (4.2 Array-to-pointer conversion) loosens the conversion requirement to (emphasis mine):
So the conversion doesn't have to happen like it pretty much always does in C (this lets functions overload or templates match on the array type).
This is also why in C you should avoid using array parameters in function prototypes/definitions (in my opinion - I'm not sure if there's any general agreement). They cause confusion and are a fiction anyway - use pointer parameters and the confusion might not go away entirely, but at least the parameter declaration isn't lying.
@Garrett 2014-07-08 02:45:01
What is an example line of code where an "expression that has type 'array of type'" is "a string literal used to initialize an array"?
@M.M 2015-03-17 03:40:19
@Garrett
char x[] = "Hello";
. The array of 6 elements"Hello"
does not decay; insteadx
gets size6
and its elements are initialized from the elements of"Hello"
.@pmg 2009-09-22 17:55:23
Arrays, in C, have no value.
Wherever the value of an object is expected but the object is an array, the address of its first element is used instead, with type
pointer to (type of array elements)
.In a function, all parameters are passed by value (arrays are no exception). When you pass an array in a function it "decays into a pointer" (sic); when you compare an array to something else, again it "decays into a pointer" (sic); ...
Function foo expects the value of an array. But, in C, arrays have no value! So
foo
gets instead the address of the first element of the array.In the comparison above,
arr
has no value, so it becomes a pointer. It becomes a pointer to int. That pointer can be compared with the variableip
.In the array indexing syntax you are used to seeing, again, the arr is 'decayed to a pointer'
The only times an array doesn't decay into a pointer are when it is the operand of the sizeof operator, or the & operator (the 'address of' operator), or as a string literal used to initialize a character array.
@Pavel Minaev 2009-09-22 19:40:50
"Arrays have no value" - what's that supposed to mean? Of course arrays have value... they're objects, you can have pointers, and, in C++, references to them, etc.
@Johannes Schaub - litb 2009-09-22 19:56:16
I believe, strictly, "Value" is defined in C as the interpretation of an object's bits according to a type. I have a hard time figuring out a useful meaning of that with an array type. Instead, you can say that you convert to a pointer, but that's not interpreting the array's contents, it just gets its location. What you get is the value of a pointer (and it's an address), not the value of an array (this would be "the sequence of values of the contained items", as used in the definition of "string"). That said, i think it's fair to say "value of array" when one means the pointer one gets.
@Johannes Schaub - litb 2009-09-22 20:01:20
anyway, i think there is a slight ambiguity: Value of an object, and value of an expression (as in, "rvalue"). If interpreted the latter way, then an array expression surely has a value: It's the one resulting from decaying it to an rvalue, and is the pointer expression. But if interpreted the former way, then of course there is no useful meaning for an array object.
@legends2k 2014-07-08 14:50:15
+1 for the phrase with a small fix; for arrays it's not even a triplet just a couplet [location, type]. Did you have something else in mind for the third location in array's case? I can't think of any.
@pmg 2014-07-08 15:55:12
@legends2k: I think I used the third location in arrays to avoid making them a special case of only having a couplet. Maybe [location, type, void] would have been better.
@Michael Krelin - hacker 2009-09-22 17:28:58
It's when array rots and is being pointed at ;-)
Actually, it's just that if you want to pass an array somewhere, but the pointer is passed instead (because who the hell would pass the whole array for you), people say that poor array decayed to pointer.
@Unheilig 2014-01-10 05:20:51
Nicely said. What would be a nice array that does not decay to a pointer or one that is prevented from decaying? Can you cite an example in C? Thanks.
@Michael Krelin - hacker 2014-01-10 09:13:55
@Unheilig, sure, one can vacuum-pack an array into struct and pass the struct.
@Michael Krelin - hacker 2014-01-10 20:08:32
I'm not sure what do you mean by "work". It's not allowed to access past the array, though it works as expected if you expect what is really to happen. That behaviour (though, again, officially undefined) is preserved.
@M.M 2015-03-17 03:42:32
Decay also happens in many situations that are not passing the array anywhere (as described by other answers). For example,
a + 1
.