0

I'm trying to create 3 arrays of type int using malloc, then initialize all 3 arrays to the same value (10) in a for look, like this:

#include <stdio.h>
#include <stdlib.h>
int main() {
    int* arr1;
    int* arr2;
    int* arr3;
    arr1 =(int*)  malloc(5* sizeof(int));
    arr2 = (int*)   malloc(5* sizeof(int));
    arr3 =(int*)  malloc(5* sizeof(int));

    for(int j = 0; j< 5 ; j++){
        *arr1 = 10;
        *arr2 = 10;
        *arr3 = 10;
        arr1 += sizeof(int);
        arr2 += sizeof(int);
        arr3 += sizeof(int);
    }

After this I reset all 3 pointers to their original position like this:

    arr1 -= (sizeof(int) * 5);
    arr2 -= (sizeof(int) * 5);
    arr3 -= (sizeof(int) * 5);

Then I want to print all the values stored, I try to do it like this:

    for(int k = 0; k < 5; k++){
        arr1 += sizeof(int);
        arr2 += sizeof(int);
        arr3 += sizeof(int);
        printf("arr1 %d\n",*arr1);
        printf("arr2 %d\n",*arr2);
        printf("arr3 %d\n",*arr3);
    }
}

I expect all the values printed to be 10 but I'm getting some random values in unexpected places like this:

arr1 10
arr2 10
arr3 10
arr1 10
arr2 10
arr3 846361185
arr1 10
arr2 10
arr3 10
arr1 10
arr2 829583969
arr3 10
arr1 10
arr2 10
arr3 0

I have absolutely no clue what is wrong, I've been stuck trying to solve this for hours without any result.

Can someone explain what's happening?.

David
  • 1
  • 1
  • (1) You should add just 1 to a pointer to get to the next element of the array — the compiler does the scaling by the size of the object pointed at. Consequently, you end up accessing data completely outside the arrays that were allocated. (2) It initially looks as though you lose track of the values returned by `malloc()` by incrementing them, but then you reset the values. However, the values were incorrectly incremented, so you access uninitialized values outside the bounds of the arrays. – Jonathan Leffler Nov 28 '22 at 04:21
  • @David, Aside: simplify `arr1 =(int*) malloc(5* sizeof(int));` --> `arr1 = malloc(sizeof arr[0] * 5);` – chux - Reinstate Monica Nov 28 '22 at 04:30

2 Answers2

1
  1. You should add just 1 to a pointer to get to the next element of the array — the compiler does the scaling by the size of the object pointed at. However, your code scales the increment by the size of an integer (4 bytes on most machines these days). Consequently, you end up accessing data completely outside the arrays that were allocated (arr1[0], arr1[4] are OK, but arr1[8], arr1[12] and arr1[16] are way outside the bounds of the allocated array).

  2. It initially looks as though you lose track of the values returned by malloc() by incrementing them, but then you reset the values. However, the values were incorrectly incremented, so you access uninitialized values outside the bounds of the arrays.

The code can be simpler — this is in keeping with your code, though it isn't the way I'd write the code:

/* SO 7459-5810 */
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    int *arr1;
    int *arr2;
    int *arr3;
    arr1 = (int *)malloc(5 * sizeof(int));
    arr2 = (int *)malloc(5 * sizeof(int));
    arr3 = (int *)malloc(5 * sizeof(int));

    for (int j = 0; j < 5; j++)
    {
        *arr1 = (j + 1) * 10 + 2;
        *arr2 = (j + 1) * 10 + 3;
        *arr3 = (j + 1) * 10 + 4;
        arr1++;
        arr2++;
        arr3++;
    }

    arr1 -= 5;
    arr2 -= 5;
    arr3 -= 5;

    for (int k = 0; k < 5; k++)
    {
        printf("arr1 %d\n", *arr1);
        printf("arr2 %d\n", *arr2);
        printf("arr3 %d\n", *arr3);
        arr1++;
        arr2++;
        arr3++;
    }

    arr1 -= 5;
    arr2 -= 5;
    arr3 -= 5;

    free(arr1);
    free(arr2);
    free(arr3);
}

When run, it produces:

arr1 12
arr2 13
arr3 14
arr1 22
arr2 23
arr3 24
arr1 32
arr2 33
arr3 34
arr1 42
arr2 43
arr3 44
arr1 52
arr2 53
arr3 54
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
1

As @JonathanLeffler told you above the compiler knows the type of the pointer and scale increment and decrements accordingly. Here is what you were trying to do:

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

#define COLS 5

int main(void ) {
    int *arr1 = malloc(COLS * sizeof(*arr1));
    int *arr2 = malloc(COLS * sizeof(*arr2));
    int *arr3 = malloc(COLS * sizeof(*arr3));
    for(int j = 0; j < COLS; j++){
        *arr1++ = 10;
        *arr2++ = 10;
        *arr3++ = 10;
    }
    arr1 -= COLS;
    arr2 -= COLS;
    arr3 -= COLS;
    for(int k = 0; k < COLS; k++){
        printf("arr1 %d\n",*arr1++);
        printf("arr2 %d\n",*arr2++);
        printf("arr3 %d\n",*arr3++);
    }
    arr1 -= COLS;
    arr2 -= COLS;
    arr3 -= COLS;
    free(arr1);
    free(arr2);
    free(arr3);
}

Here is what you should do instead:

#include <stdio.h>

#define ROWS 3
#define COLS 5

int main(void ) {
    int arr[ROWS][COLS] = {
        {10, 10, 10, 10, 10},
        {10, 10, 10, 10, 10},
        {10, 10, 10, 10, 10}
    };
    for(size_t c = 0; c < COLS; c++)
        for(size_t r = 0; r < ROWS; r++)
            printf("arr%zu %d\n", r + 1, arr[r][c]);
}

Ideally you want to swap those two for loops so you iterate over rows then columns for better performance. If the initialization bothers you set arr[r][c] = 10; before the print statement instead.

Allan Wind
  • 23,068
  • 5
  • 28
  • 38