1

Possible Duplicate:
How do I use arrays in C++?

void fn(int a[3])
{
    a[5]=5;
}

int main()
{
    int A[10] = {0};
    cout<<A[5]<<endl;
    fn(A);
    cout<<A[5]<<endl;
}

For the first print statement I got A[5]=0 and for the second time A[5]=5. How does this code actually work ?

Community
  • 1
  • 1
sp497
  • 2,363
  • 7
  • 25
  • 43

3 Answers3

3

In C++ array from programmer's view is almost equal to the pointer to its first element. In case of arrays passed by parameter, they are equal. If you imagine it this way, you pass the pointer to an array to function, then modify its sixth element (still the original!), and then display it.

Your code is equal to:

void fn2(int * a)
{
    *(a + 5) = 5;
}

(...)

fn(&(A[0]));

Side note The difference in statically allocated and dynamically allocated arrays can be seen while playing around with local variables:

int a[5];
int * p;

printf("%d %d\n", sizeof(a), sizeof(p));
Spook
  • 25,318
  • 18
  • 90
  • 167
  • The code is *exactly* equal to that. – Oliver Charlesworth Jan 03 '13 at 10:53
  • So writing int a[3] does not matter ? – sp497 Jan 03 '13 at 10:55
  • It does. C++ treats dynamically and statically allocated arrays a little bit different. For instance, you can pass statically allocated array by parameter (eg. int[6]), but not dynamically alocated (eg. int[] - you have to use pointer instead). – Spook Jan 03 '13 at 10:56
  • @Spook: I'm not sure what you mean by your above comment, but it doesn't sound right! – Oliver Charlesworth Jan 03 '13 at 10:57
  • When you pass statically allocated array as parameter, C++ *knows*, that it's an array (even sizeof will behave correctly). If you dynamically allocate an array, you can only pass it by pointer and sizeof() will show only size of the first element. This is core difference between my code and OP's and this is why I wrote "almost" and not "exactly". – Spook Jan 03 '13 at 10:59
  • @Spook: Arrays are *always* converted to pointer-to-first element when passed as args to a function (unless the function takes an array by reference). So the OP's code is **exactly** identical to your code. – Oliver Charlesworth Jan 03 '13 at 11:00
  • @OliCharlesworth Another example. You can easily exceed bounds of dynamically allocated array, but if you try to do so with statically allocated array, compiler will emit warning C4789 (VS). Again: C++ compiler sees difference between int[3], which is a statically allocated array and int * which is a pointer-to-int (possibly an array). – Spook Jan 03 '13 at 11:00
  • @Spook: It's also trivial to exceed the bounds of a static array in a way that the compiler can't detect. – Oliver Charlesworth Jan 03 '13 at 11:02
  • @Spook: There is no difference between `int[3]` and `int*` in the context of a function prototype. – Oliver Charlesworth Jan 03 '13 at 11:03
  • @OliCharlesworth If so, call sizeof() on the parameter and check if there is really no difference. – Spook Jan 03 '13 at 11:03
  • @Spook: See e.g. http://ideone.com/sj0sAM. – Oliver Charlesworth Jan 03 '13 at 11:05
  • Even in fn() if I change a[5]=5 to a[12]=6 and print a[12] in main everything is working fine even if it is outside the bounds !!! – sp497 Jan 03 '13 at 11:05
  • Ok, I stand corrected. There *is* a difference in local variables. There seems not to be one while passing arrays by parameters. I've edited the answer to reflect the discussion. – Spook Jan 03 '13 at 11:10
2

You code:

void fn(int a[3])
{
    a[5]=5;
}  

Is equivalent to code:

void fn(int* a)
{
    a[5]=5;
}  

Fortunately you can check it by by compile your code with -S option to gcc (or g++).
You will get same assembly output for Both: (output file will be with .s extension)

fn:
    pushl   %ebp
    movl    %esp, %ebp
    movl    8(%ebp), %eax    // base address assign to eax register.
    addl    $20, %eax        // a[5] , because 5*4 = 20, so eax = eax + 20
    movl    $5, (%eax)       // this is =5 , (%eax) = 5
    popl    %ebp
    ret
    .size   fn, .-fn
    .section    .rodata     

Both Code use only base address pass to the fu() function.

there is nothing about size 3 of argument

Grijesh Chauhan
  • 57,103
  • 20
  • 141
  • 208
  • 1
    This question requires *standard* proof, not practical proof. – Griwes Jan 03 '13 at 11:08
  • "there is nothing about size 3 of argument" - but only in case of *this particular code*. Try to call sizeof() on int* and int[3]. – Spook Jan 03 '13 at 11:08
  • @Spook and Griwes Ok! I agree with both of you, OP can consider it if he like. – Grijesh Chauhan Jan 03 '13 at 11:11
  • No concrete answers yet !! – sp497 Jan 03 '13 at 11:14
  • And I thought it would be helpful in some way! – Grijesh Chauhan Jan 03 '13 at 11:14
  • 1
    And what concrete answers would you expect? Maybe you should state more clearly, what do you want to know? – Spook Jan 03 '13 at 11:15
  • You said "Ok, I stand corrected. There is a difference in local variables. There seems not to be one while passing arrays by parameters." Is it defined in the C++ standard ? – sp497 Jan 03 '13 at 11:19
  • @srinivasprabhu Have you got your answer? – Grijesh Chauhan Jan 03 '13 at 11:23
  • @Spook I tried with `sizeof()` for both `int* and int[3]` still same code!!..II even myself bit unclear at this point. – Grijesh Chauhan Jan 03 '13 at 11:35
  • Read my answer. sizeof() will return different result for a local variable. For a parameter it'll always return the same value. All I want to say is that generically int[3] and int * are *different* beings even when passing by a parameter changes them both to int *. – Spook Jan 03 '13 at 13:35
-1

If you want to pass the address of A to change the array itself:

fn(int **A)
Taryn
  • 242,637
  • 56
  • 362
  • 405
DayDayHappy
  • 1,679
  • 1
  • 15
  • 26