0

I`m trying to get the sum of two arrays using pointers, but when the output comes all are zeros, what can I do?

And please if there a better way to do it I would like to know

Here`s the code

UPDATE

#include  < cstdio >  
#include < iostream >

using namespace std;

unsigned i;

int main(){

/* Array`s input */

    short A[3];

    for( i = 0 ; i < 3 ; i++ ){

    printf("Insert number for [A]: ");
    scanf("%hd",&A[i]);

    }

    printf("\n");

    short B[3];

    for( i = 0 ; i < 3 ; i++ ){

    printf("Insert number for [B]: ");
    scanf("%hd",&B[i]);

    }

    short C[3];

// Pointers

    short *punt_A, *punt_B, *punt_C;

    punt_A = &A[0];
    punt_B = &B[0];
    punt_C = &C[0];

// Addition

    for( i = 0 ; i < 3 ; i++ ){

    C[i]=punt_A[i]+punt_B[i];

    }

    printf("\n\nArray addition = { %d, %d, %d }\n", *punt_C, *(punt_C + 1), *(punt_C + 2));



return 0;

}
πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
Bit87
  • 65
  • 9
  • Why didn't you print out the result of the arrays first, so that we can know what your real intentions are with the pointers? Also, why write a tricky loop like this: `for( i = 3; i-- ; )` What's wrong with simply `for(int i = 0; i < 3; ++i )`? – PaulMcKenzie May 21 '16 at 01:20
  • 1
    `scanf("%d",&A[i]);` `%hd` for short --> `scanf("%hd",&A[i]);` – BLUEPIXY May 21 '16 at 01:24
  • 3
    This post is a wonderful example of trying to be clever and outwitting yourself. –  May 21 '16 at 01:24
  • regarding this line: `# include < stdio.h >`, since this code is for C++, the line should be: `# include < cstdio >` – user3629249 May 21 '16 at 01:25
  • If you used C++'s `cin`, stopped trying to outwit yourself (thanks @Hurkyl) writing weird loop constructs, you would have at least a chance to get to the pointer section without undefined behavior from occurring. – PaulMcKenzie May 21 '16 at 01:26
  • The code is OK (although a bit weird) except for the scanf format specifier, and the last `printf`, which should be inside the loop and before the `++` lines – M.M May 21 '16 at 01:36

4 Answers4

2

Remember short A[3]; will allow you to legally access A[0]..A[2]

In

for( i = 3; i-- ; )
{
/* i-- is a tricky way of entering the loop
 * This checks i for the condition, and passes (i-1, the current value
 * of i) to the loop
 * Though the method is smart I think it is less readable
 * There is no access violation here, forgive my previous comment :(
 */
printf("Insert number for [A]: ");
scanf("%hd",&A[i]);  // Remember %hd for short.

}

Addition here may be better represented as :

for( i = 0; i<3;i++){ 
/* I changed the forloop structure which may be used 
 * for reading the arrays too. In fact this has no surprises.
 */
C[i]=punt_A[i]+punt_B[i]; // Or *(punt_A+i) + *(punt_B+i)

}

Regarding,

printf("\n\nArray addition = { %d, %d, %d }\n", *punt_A, *punt_B, *punt_C );

This prints only A[0],B[0],C[0] respectively and your format specifier "%d" doesn't match the type short. The right specifier is "%hd". Print the result array using a loop.

sjsam
  • 21,411
  • 5
  • 55
  • 102
  • 2
    The loop does not access `A[3]` – M.M May 21 '16 at 01:34
  • 2
    @sjsam See the condition in the for loop, it's executed before the body, hence `A[2]` is the 1st index accessed. – πάντα ῥεῖ May 21 '16 at 02:46
  • @πάνταῥεῖ : thankyou for the f/b. I thought since `i--` is postfix the previous value of i would go inside the loop body and forgot the fact that condition itself makes a sequence point. Anyway I think the forloop style is bad. Updating the answer in a moment :) – sjsam May 21 '16 at 02:59
  • @M.M : Updated the answer, thanks for the feedback. :) – sjsam May 21 '16 at 03:13
  • I'm pretty sure `short`s get upgraded to `int`s when passed as parameters like that, so `%d` is correct. –  May 21 '16 at 12:40
  • @Hurkyl : I agree , but still he could use the right format specifier. – sjsam May 21 '16 at 12:56
1

punt_A, punt_B, punt_C are all left pointing one element past the end of their respective arrays, eg punt_A is now pointing at A[3]. The arrays are allocated on the stack along word boundaries, so there is "dead space" after each array on the stack. In a Windows debug build, uninitialised areas are marked with 0xcccccccc so I see -13108 which is (short)(0xcccccccc). In a release build, you just see whatever was left in that memory address from before, which in many cases is just zero.

I did a double take when I saw for (i = 3; i--; ). You've put i-- where the check condition normally goes. It's clearer to use for (i = 2; i >= 0; i--; ). It does actually work by accident because when the condition i-- is evaluated, it takes the i and checks whether that condition is nonzero. After the check, i gets decremented and enters the loop. When i becomes zero, the loop terminates. So inside the loop you see i = 2, 1, 0. The post-decrement operator is applied after any evaluations, eg, if int n = 1; then n + n--; returns 2, not 1. n is decremented after the expression is evaluated.

John D
  • 1,627
  • 1
  • 11
  • 10
  • `for (i = 2; i >= 0; i--; )` breaks if `i` is unsigned, unlike OP's version – M.M May 21 '16 at 03:08
  • True! `for (i = 0; i < 3; i++;)` is better as it works for signed or unsigned. However I was trying to stay as close to OP's code as possible. But good point. – John D May 21 '16 at 03:22
  • -13108 is simply 0xCCCC and that indeed [indicates uninitialized memory access](https://stackoverflow.com/q/370195/995714). You don't need to say `(short)(0xcccccccc)` – phuclv Aug 18 '18 at 11:38
0

Several things:

  • Your arrays and pointers are declared as short, but scanf()/printf() specifiers are %d, which mean int. Typically short is a 16-bit integer, and int is a 32-bit integer. That can cause weird effects.
  • You should start your loops at 2 instead of 3. 3 is already outside bounds.
  • At the end of the final loop, all pointers will point beyond the ends of arrays, but you pass them to printf() anyway (which is actually undefined behavior).
  • As a matter of fact, don't you want to output the contents of C[] - the addition results? Why are you using punt_A and punt_B there?
Vilx-
  • 104,512
  • 87
  • 279
  • 422
0

Now this is rough fix for ur program

#include <stdio.h>
#include <iostream>

using namespace std;

unsigned i;

int main(){


/* Array`s inputs */

    int *A = new int[3];

    for( i = 3 ; i-- ; ){

        cout << "Insert number for [A]: " << endl;
        scanf("%d",&A[i]);
    }

    printf("\n");

    int* B = new int[3];

    for( i = 3; i-- ; ){

    cout << "Insert number for [B]: " << endl;
    scanf("%d",&B[i]);

    }

    int* C = new int[3];

// Pointers

    int *punt_A, *punt_B, *punt_C;

    punt_A = A;
    punt_B = B;
    punt_C = C;

// Addition

    for( i = 3; i--; ){

    *punt_C = *punt_A + *punt_B;
    punt_A++;
    punt_B++;
    punt_C++;

    }

    for(int i = 0; i < 3; i++)
    {
        cout << *C << endl;
        C++;
    }

delete [] A;
delete [] B;
delete [] C;
return 0;
}
  • In your program:

The problem was: You initialize an array of shorts. Size of short is 2 bytes. However, you are loading number, expecting integer %d wich is 4 bytes. So, you load in the 2 bytes, and the other two bytes just ommited. I compile it WITHOUT -Wall -pedantic flags and still get warning:

main.cpp: In function ‘int main()’:
main.cpp:17:21: warning: format ‘%d’ expects argument of type ‘int*’, but argument 2 has type ‘short int*’ [-Wformat=]
     scanf("%d",&A[i]);
                     ^
main.cpp:28:21: warning: format ‘%d’ expects argument of type ‘int*’, but argument 2 has type ‘short int*’ [-Wformat=]
     scanf("%d",&B[i]);

Now to fix this, make them all ints. But you asked for better solution. If you are given two arrays, and you have to sum them, and since you are using c++11, for you, it might be easier to use a container.

# include <stdio.h>
# include <iostream>

#include <vector>

#define COUNT 3

using namespace std;

unsigned i;

int main()
{
/* Array`s inputs */

    vector<int> A, B;

    int worker;

    for( i = COUNT ; i-- ; )
    {
        cout << "Insert number for [A]: " << endl;

        cin >> worker;
        A.push_back(worker);
    }

    for( i = COUNT ; i-- ; )
    {
        cout << "Insert number for [B]: " << endl;

        cin >> worker;
        B.push_back(worker);
    }

    for(int i = 0; i < COUNT; i++)
    {
        A[i] = A[i] + B[i];
    }
    cout << "summed up" << endl;

    for(vector<int>::iterator it = A.begin(); it != A.end(); it++)
    {
        cout << *it << endl;
    }
return 0;
}

Now notice, i made a define for your count. Moreover, I used aray A again for output, saving space. The problem is, that vector by itself has O(n) complexity for push_back() (unless you resrve the size, but that requires knowing exact number of inputs, wich might not be in future a case, you might load until EOF). To eliminate this and make the program faster, a list might be used for better performance.

But if you WANT to use pointers, use iterators. :]

(please notice that my code is not protected for fails, meaning that if you put in a letter, it will do strange thing, but i outlined the idea :]

Jan Glaser
  • 364
  • 2
  • 14
  • Ye :] C++ is quite hard to learn :S Whenever you would need a help or need to explain something, you can write me (hope this has a possibility of private messages). There are lot of things in C++ and there is long path ahead of you. I burned myself coutless times in past :] – Jan Glaser May 21 '16 at 02:12