0

I have started an introductory class to C. I cannot explain the output that I get from running the code below

./a.out 6

Output is:

Array A elements: 0 1 2 3 4 5 
Array B elements: 1 2 3 4 5 796830176

What I think the code is doing: When manup_array is executed, each value of the respective pointers will be incremented, but since it is post-fix, this takes effect only later on after the original value is returned.

True enough, when we print array A first, we get 0 1 2 3 4 5 (i.e. before incrementation). Subsequently when we print array B, the incrementation takes effect, so we get 1 2 3 [...]

What really puzzles me is why the last number is 796830176. Also, running this on various computers produces a different last number every time, suggesting that the pointer addressing is somehow responsible for this.

Could someone explain this to me?

Note: The outputs of each array are identical (1 2 3 4 5 6) if I use the pre-fix operator. This is consistent with what I think is going on -> the pointers don't change; only the values get updated.

#include <stdio.h>
#include <stdlib.h>

void manup_array(int *array[], int n); // Forward declaration.

int main(int argc, char *argv[])
{
    // The size N of 2 arrays are the same; obtain them from cmd line.
    int N = atoi(argv[1]); // Convert from str to int in C.

    int arrayA[N];  // Declare integer array.
    int *arrayB[N]; // Declare integer pointer array.

    for (int i = 0; i < N; i++)
    {
        arrayA[i] = i;
        arrayB[i] = &arrayA[i]; // Assign address of each element in A to element in B.
    }

    manup_array(arrayB, N);

    printf("Array A elements: ");
    for (int i = 0; i < N; i++)
    {
        printf("%d ", arrayA[i]);
    }

    printf("\n");

    printf("Array B elements: ");
    for (int i = 0; i < N; i++)
    {
        printf("%d ", *arrayB[i]);
    }

    printf("\n");

    return 0;
}

void manup_array(int *array[], int n) { // Take in B as input, then increase each elem by 1
    for (int i = 0; i < n; i++)
    {
        *array[i]++;
    }
}
2
  • Did you write this or was it handed as an example you should learn from? In case of the latter, throw a tomato at your teacher and just forget about the whole thing; you wouldn't write code like this in a real application... Commented Feb 10, 2014 at 8:44
  • The []-operator binds tighter then the *-operator. So review your code for where both are applied to the same variable, and check whether their use really does is intended. Commented Feb 10, 2014 at 9:09

3 Answers 3

1

This is really obscure code. What is does:

The function takes an array of pointers as parameter. Since the parameter to the function had type int *array[], any change of the items of array will affect the caller and alter arrayB.

The interesting part of the function is *array[i]++;. The operator precedence rules in C state that [] has higher prio than postfix ++, which has higher prio than unary *.

Since array is an array of pointers, array[i] gives you a pointer. Not a the value it points at. Then ++ increments the pointer to point at the next item in the arrayA of main.

And then finally there is a * which takes the contents of what that pointer pointed at, and then does nothing with them. The * is superfluous and just there to confuse the reader.

So back in main, you have changed all the pointers of arrayB. arrayB[0] now points at arrayA[1] and so on. The last item of arrayB will point one item past the end of arrayA, so for the last item, you access the array out-of-bounds and get a garbage value.

Sign up to request clarification or add additional context in comments.

5 Comments

Lesson learned is probably to never mix ++ with other operators. It is an incredibly common cause for bugs in C.
Thank you! Excellent explanation of what happened; realized that I was wrong in my way of thinking. Specifically, I was mistaken that I was actually increasing the value which the pointer was pointing at, because I didn't take into account the operator precedence.
I was also mistaken about how postfix operator works in trying to explain what I saw. This was indeed a class question. We were supposed to try to get an output such as: A: 0 1 2 3 4 5 B: 1 2 3 4 5 4732439 We were supposed to "increase each element of [array B] by 1".
@kevinze Please note that accessing an array out-of-bounds is aways a bug, because you invoke undefined behavior. You aren't guaranteed to get a garbage value - you might as well get a "segmentation fault" runtime crash, or the program could even go completely haywire. Your teacher should point this out, so that no student starts writing programs that rely on "getting garbage values".
Thank you!! Indeed, I did get some segmentation fault errors too.
0
void manup_array(int *arr[], int n) { // Take in B as input, then increase each elem by 1
    for (int i = 0; i < n; i++)
    {
        int val = (*arr[0]); // get the value pointed to by the current value of arr
        val++;               // increment it
        *(arr[0]) = val;     // assign it back
        arr++;               // increase the pointer
    }
}

Incredibly obtuse, but it demonstrates what you mean to do and how your obscure code muddled up the operators.

To add, makes debugging way easier!

1 Comment

Except, if he wrote this himself, he probably didn't intend to increase the pointer. Plus you mixed up arr++ with arr[i]++. Also you got a typo [0] where [i] was intended.
0

manup_array() increments the pointer, not the value as expected.

Modified manup_array().

void manup_array(int *array[], int n) { // Take in B as input, then increase each elem by 1
    for (int i = 0; i < n; i++)
    {
        //*array[i]++;
        (*array[i])++;
    }
}

I suggest to refer Pointer Arithmetic: ++*ptr or *ptr++?

5 Comments

You should be ok with just (*array[i])++;. The issue here is that *array[i]++ gets read as *array[i] = *(array[i] + 1);, due to the order of operations c uses.
@RedAlert Can you please elaborate.
your modified manup_array() converts to *array[i] = (*array[i]) = (*array[i]) + 1; after the ++ is parsed, which is a bit redundant.
I'm pretty sure *array[i] = (*array[i])++; is undefined behavior. You have two writes to array in the same operation without a sequence point in between. Anyway, don't teach people to write code like that...
@Lundin mistakenly added array[i] = (*array[i])++;. I feel (*array[i])++; will do the job.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.