Theory question on C and array passing

Started by
19 comments, last by SiCrane 16 years, 1 month ago
Quote:Original post by Hodgman
Yes, arrays are just pointers behind the scenes.
This is not accurate. Arrays identifiers decay to pointers when use in pointer context, but you statement makes it sound like an array is a pointer on the stack that points to a memory block in the heap. This is not the case. Only the memory is on the stack, and no special pointer is saved to it, except the offset from function stack frame.

In fact it is possible to pass arrays as array references, which do not decay to pointers.
Advertisement
Quote:Yes, arrays are just pointers behind the scenes.


This is a perfectly fine statement that accurately captures what goes on - excepting pretty complex stuff about a c/c++ compiler's handling of declarator syntax.

Quote:[...] makes it sound like an array is a pointer on the stack that points to a memory block in the heap. This is not the case. Only the memory is on the stack, and no special pointer is saved to it, except the offset from function stack frame.


func() { static int ia[ 100] }

The contiguous memory for the symbol 'ia' is definately not on the stack.
Quote:Original post by chairthrower

func() { static int ia[ 100] }

The contiguous memory for the symbol 'ia' is definately not on the stack.


So? "static" variables are different, was that your point? The most common use case for arrays is on the stack, or as part of an aggregate type.
Quote:Original post by chairthrower
Quote:Yes, arrays are just pointers behind the scenes.
This is a perfectly fine statement that accurately captures what goes on - excepting pretty complex stuff about a c/c++ compiler's handling of declarator syntax.
An array is a contiguously allocated non-empty set of objects of a particular type. The location of the array is implicitly known to the program during execution, usually relative to the current stack. A pointer is an indirect descriptor of an object at an unknown location. While arrays and pointers share many similarities in many contexts (often due to the ease with which an array will decay to a pointer to its first element) there are also many important differences. They are most assuredly not the same thing, either behind the scenes or in front of them.

Σnigma
Maybe it would be better to think of decay as applying to the expression operators & and =

int ia[ 100];
int *pa = ia; // decay
void func() { }
void (*pfunc)();
pfunc = func;
pfunc = &func // decay

And think of arrays in functions signatures such as,

void func( int ia[ 100]) { }

as 'mislabled pointers' mascarading as arrays since the location of the contiguous memory is *not* known at compile or runtime unlike other use-cases of arrays where the array memory is predetermined either in the stack frame or in some binary data section of the object file. The argument that "parameter arrays" are not really arrays but are pointers seems to be pretty reasonable if we are considering the problem from a low level assembly/implementation point of view.

The counter argument to this is from a language and higher level semantic perspective. From this point of view we can consider that the parameter declarator typing is fully explicit (it looks just like an array). eg sizeof( ia) is known and behaves just as we expect. In all cases it is a normal array declarator and responds in the same way as normal arrays to the application of & [] and = operators.

Irrespective of whether a parameter array declarator should propertly be characterised as an 'array' or not - the compiler is distinguishing (and hiding from the programmer) a parameter array's behaviour from 'normal' arrays at both high (semantic) and low (assembly output) levels
<edit for clarity>
Quote:The argument that "parameter arrays" are not really arrays but are pointers seems to be pretty reasonable if we are considering the problem from a low level assembly/implementation point of view.

The argument that "parameter arrays" are not really arrays but are pointers is explicit in the C++ Standard:
Quote:C++ Standard, Section 8, Paragraph 3
<snip /> After determining the type of each parameter, any parameter of type "array of T" or "function returning T" is adjusted to be "pointer to T" or "pointer to function returning T," respectively. <snip />
Quote:The counter argument to this is from a language and higher level semantic perspective. From this point of view we can consider that the parameter declarator typing is fully explicit (it looks just like an array). eg sizeof( ia) is known and behaves just as we expect. In all cases it is a normal array declarator and responds in the same way as normal arrays to the application of & [] and = operators.
As evidenced above, this counter argument is incorrect.

Σnigma
Apologies for the rather brief argument above, I shall expand on it now that I have a bit more time. Firstly, I forgot we were dealing with C in this thread, not C++, so the above quote from the C++ Standard is only relevant in that it is a rephrasing of the language in the C standard (or at least the draft of which I have a copy):
Quote:C Standard Draft, Section 3.7.1
<snip /> A declaration of a parameter as "array of type" shall be adjusted to "pointer to type," and a declaration of a parameter as "function returning type" shall be adjusted to "pointer to function returning type," as in 3.2.2.1. <snip />
Quote:Original post by chairthrower
The counter argument to this is from a language and higher level semantic perspective. From this point of view we can consider that the parameter declarator typing is fully explicit (it looks just like an array). eg sizeof( ia) is known and behaves just as we expect. In all cases it is a normal array declarator and responds in the same way as normal arrays to the application of & [] and = operators.
Applying the above quote from the standard we can analyse the claims of this argument:
  • claim: sizeof(ia) is known and behaves just as we expect.
    refutation: sizeof(ia) behaves according to the adjusted type of ia, which is int *. I compiled the following program under Visual C++ 2008, MinGW gcc 3.3.1 and Borland 5.8.2:
    #include <stdio.h>void func(int array[7]){	printf("%d\n", sizeof(array));}int main(){	int array[7];	printf("%d\n", sizeof(array));	func(array);}
    The results were unanimous:
    284
  • claim: In all cases it is a normal array declarator and responds in the same way as normal arrays to the application of & [] and = operators.
    refutation: The following program demonstrates that ia as a function parameter does not behave as a normal array:
    /*  1 */ int func(int ia[1000], int ib[2])/*  2 */ {/*  3 */ 	int * * iap = &ia/*  4 */ 	ia = ib;/*  5 */ 	++ia;/*  6 */ 	return **iap + *ia; // avoid unused variable warnings/*  7 */ }/*  8 */ /*  9 */ int main()/* 10 */ {/* 11 */ 	int ia[1000];/* 12 */ 	int ib[2];/* 13 */ 	int * * iap = &ia/* 14 */ 	ia = ib;/* 15 */ 	++ia;/* 16 */ 	return **iap; // avoid unused variable warnings/* 17 */ }Visual C++ 2008:array_parameter2.c(13) : warning C4047: 'initializing' : 'int **' differs in levels of indirection from 'int (*)[1000]'array_parameter2.c(14) : error C2106: '=' : left operand must be l-valuearray_parameter2.c(15) : error C2105: '++' needs l-valueMinGW gcc 3.3.1:array_parameter2.c: In function `main':array_parameter2.c:13: warning: initialization from incompatible pointer typearray_parameter2.c:14: error: incompatible types in assignmentarray_parameter2.c:15: error: wrong type argument to incrementBorland 5.82:Warning W8075 array_parameter2.c 13: Suspicious pointer conversion in function mainError E2277 array_parameter2.c 14: Lvalue required in function mainError E2277 array_parameter2.c 15: Lvalue required in function main
Σnigma
So what you're basically saying, Enigma, is that:

void func (int myarray[5]);


=

void func (int* myarray);


Right?
while (tired) DrinkCoffee();
Quote:claim: sizeof(ia) is known and behaves just as we expect.
refutation: sizeof(ia) behaves according to the adjusted type of ia, which is int *. I compiled the following program under Visual C++ 2008, MinGW gcc 3.3.1 and Borland 5.8.2:



I had the belief that parameter array declarators behaved like normal arrays so ingrained in my mind that I didnt even bother to test the counter-example I gave before posting. hmmmmn and I even used to work on c/c++ compiler front ends about 10 years ago.

Thanks for taking the time to correct misinformation.
Quote:Original post by polymorphed
So what you're basically saying, Enigma, is that:
Right?


Exactly.

This topic is closed to new replies.

Advertisement