Reputation: 1333
#include <cstdlib>
#include <iostream>
using namespace std;
void f(int k[0]){ --k[1]; }
void g(int *k){(*(--k))++;}
void h(int k[1]){--k;}
int main(){
int k[]={1,2,3,4};
f(k+2);
g(k+2);
h(k+2);
for (int i = 1; i < 4; i++)
cout << k[i];
}
Correct output is 333
but I thought it was 334
.
I do not understand what exactly happen in function f with the instruction --k[1]
. I could agree with the correct output if the code was k[0]--
. What's the difference?
Thanks
Upvotes: 0
Views: 72
Reputation: 882716
With a slight change to the code, you can see what each step is doing:
#include <cstdlib>
#include <iostream>
using namespace std;
int *globk;
void dumpk(int *pk) {
cout << "Array:";
for (int i = 0; i < 4; i++)
cout << ' ' << globk[i];
cout << ", k at index " << (pk-globk) << '\n';
}
void f(int k[0]) { dumpk(k); --k[1]; dumpk(k); }
void g(int *k) { dumpk(k); (*(--k))++; dumpk(k); }
void h(int k[1]) { dumpk(k); --k; dumpk(k); }
int main(){
int k[]={1,2,3,4};
globk = k; // save for detecting where k is
f(k+2);
g(k+2);
h(k+2);
// slightly prettier output.
for (int i = 1; i < 4; i++)
cout << k[i] << ' ';
cout << '\n';
}
The output of that shows what each step does:
Array: 1 2 3 4, k at index 2
Array: 1 2 3 3, k at index 2
--k[1]; // -- array VALUE at INDEX 3 (2+1) down to 3
Array: 1 2 3 3, k at index 2
Array: 1 3 3 3, k at index 1
(*(--k))++; // -- POINTER to [1], then ++ that VALUE up to 3
Array: 1 3 3 3, k at index 2
Array: 1 3 3 3, k at index 1
--k; // Simply -- POINTER with no change to any VALUE
Upvotes: 1
Reputation: 106244
--k[1]
decrements the value at k[1]
, and given f(k+2)
means the f()
-local k
points to the caller's (i.e. main()
's) k[2]
, and the 1 and 2 indices add, you're actually decrementing the caller's k[3]
from 4 to 3.
k[0]--
would decrement the variable at *k
, which for f
would be known as k[2]
in the caller's context.
The important insights for understanding this code are:
all the functions f
, g
and h
ultimately get a pointer to an int
, and their notion of "k
" is completely independent of the caller's notion of k
, specifically - it's offset 2 int
s further into the caller's k
array,
operator precedence: specifically, prefix decrement is applied after array subscripting in --k[1]
.
That said, paxdiablo certainly has a point... ;-).
Upvotes: 1
Reputation: 4961
f and g are modifying values, while h is modifying an address:
f(int k[0]){ --k[1]; }
f take one parameter, an array of int; k[1] is the same as k++ in this case; the function is decrementing the value of the element situated at the next address vs the one passes as argument. So It's decrementing k[3] in your main.
g is relatively straight forward and I think you figured that out.
h is similar to f
h(int k[1]){--k;}
h takes a int array as input and it decrements the address passed as argument.
Hope this helps
Upvotes: 0
Reputation: 154047
First, all three functions have exactly the same signature. It would be less confusing if it had been written:
void f(int* pi){ --pi[1]; }
void g(int* pi){(*(--pi))++;}
void h(int* pi){--pi;}
(I've changed the name of the argument to avoid ambiguity in the following discutions.)
Also, of course: a[b]
is, by definition, *(a + b)
, and that any operation on k
will convert it from int[4]
to int*
, pointing to the first element.
So we get the following results:
f( k + 2 );
// In f, pi is k + 2, so `pi[1]` is *(k + 3).
// After f, k = { 1, 2, 3, 3 }
g( k + 2 );
// In g, pi starts out as k + 2; it is then decrementd to give k + 1
// After g, k = { 1, 3, 3, 3 }
h( k + 2 );
// In h, pi is k + 2. A local copy of k + 2, so h doesn't change
// k at all.
The results are that k
is { 1, 3, 3, 3 }
after the four operations.
Upvotes: 1
Reputation: 521
What this code is doing is:
Pass a an array starting at the 3rd element in k[]
to f
. f
takes a 1-dimensional array and decreases its 2nd element (in this case it will be k[4]
which will change its value of 4 to 3).
Pass a pointer of the 3rd element in k[]
to g
. g
takes a pointer to an integer or array, and first decreases the value of the pointer (becoming now a pointer to the 2nd element of k[]
) and then increases the value of what's pointed, changing it from 2 to 3.
Pass a an array starting at the 3rd element in k[]
to h
. ``h receives a 1-dimensional array and decreases the pointer to the array (not the value it points to) thus not modifying the values of the pointed array.
Upvotes: 0