0

I'm new at C. Here is a function, one of its' proposes is to fill the sizes, and I have problems with it. I fill it correctly, but then, in perform(), where I call marray_read() from, sizes is filled with zeros.

int64_t** marray_read( size_t* rows, size_t* sizes[] ) {
    size_t n = read_size();
    *rows = n;
    sizes = malloc(n * sizeof(size_t));
    
    int64_t **array = (int64_t **)malloc(n*sizeof(int64_t*));
    size_t m = 0;
    for (size_t i = 0; i < n; i++) {
        m = read_size();
        sizes[i] = m;
        array[i] = (int64_t *)malloc(m*sizeof(int64_t));
        for (size_t j = 0; j < m; j++) {
            array[i][j] = read_int64();
        }
    }
    for (size_t i = 0; i < n; i++) {
        printf("%zu ", sizes[i]);
    }
    printf("\n");
    return array;
}

void perform() {
    size_t rows;
    size_t* sizes;
    int64_t** marray = marray_read(&rows, &sizes);
    for (size_t i = 0; i < rows; i++) {
        printf("%zu ", sizes[i]);
    }
    // Output for rows=3 is: 0 0 0
}

I have already read this, but when I use memcpy(), everything is still ok in marray_read(), but I get Segmentation fault in perform():

int64_t** marray_read( size_t* rows, size_t* sizes[] ) {
    size_t n = read_size();
    *rows = n;
    memcpy(sizes, malloc(n * sizeof(size_t)), (n * sizeof(size_t)));
    
    int64_t **array = (int64_t **)malloc(n*sizeof(int64_t*));
    size_t m = 0;
    for (size_t i = 0; i < n; i++) {
        m = read_size();
        sizes[i] = m;
        array[i] = (int64_t *)malloc(m*sizeof(int64_t));
        for (size_t j = 0; j < m; j++) {
            array[i][j] = read_int64();
        }
    }
    for (size_t i = 0; i < n; i++) {
        printf("%zu ", sizes[i]);
    }
    printf("\n");
    return array;
}

void perform() {
    size_t rows;
    size_t* sizes;
    int64_t** marray = marray_read(&rows, &sizes);
    for (size_t i = 0; i < rows; i++) {
        printf("%zu ", sizes[i]);
    }
    // Output: Segmentation fault
}

I need to realise this function without memcpy(), but I'm interested in any way to do it.

Paul R
  • 208,748
  • 37
  • 389
  • 560
vasyok03
  • 21
  • 5
  • `sizes = malloc(n * sizeof(size_t))` shouldn't this be `*sizes = malloc(n * sizeof(size_t))`... and in general all the dereferencing of `sizes` should be with an additional `*`, like `*sizes` – xanatos Jan 01 '21 at 11:25
  • I also tried this way, but I get Segmentation fault in **perform()** anyway: `printf("%zu\n", sizes[0]);` - Segmentation fault happens here, in **perform()** – vasyok03 Jan 01 '21 at 11:33
  • 1
    This would be all easier with a `struct the_data { int64_t *data; size_t size; }` and then an array of such structures. – KamilCuk Jan 01 '21 at 11:43

1 Answers1

0

You forgot to dereferce (*sizes):

#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>

size_t read_size(void) {
    size_t n;
    scanf("%zu", &n);
    return n;
}

int64_t read_int64(void) {
    int64_t n;
    scanf("%" SCNd64, &n);
    return n;
}

int64_t** marray_read(size_t* rows, size_t* sizes[]) {
    size_t n = read_size();
    *rows = n;

    *sizes = malloc(n * sizeof(size_t));
    int64_t** array = malloc(n * sizeof(int64_t*));

    for (size_t i = 0; i < n; i++) {
        size_t m = read_size();
        (*sizes)[i] = m;
        array[i] = malloc(m * sizeof(int64_t));
        for (size_t j = 0; j < m; j++) {
            array[i][j] = read_int64();
        }
    }
    for (size_t i = 0; i < n; i++) {
        printf("%zu ", (*sizes)[i]);
    }
    printf("\n");
    return array;
}

void perform(void) {
    size_t rows;
    size_t* sizes;
    int64_t** marray = marray_read(&rows, &sizes);
    for (size_t i = 0; i < rows; i++) {
        printf("\n%zu:", sizes[i]);
        for (size_t j = 0; j < sizes[i]; j++) {
            printf(" %" SCNd64, marray[i][j]);
        }
    }

    free(sizes);

    for (size_t i = 0; i < rows; i++) {
        free(marray[i]);
    }

    free(marray);
}

int main(void) {
    perform();
    return 0;
}

I've added code to print the resulting values, and to free the arrays. You can check at https://ideone.com/SSPoNg .

xanatos
  • 109,618
  • 12
  • 197
  • 280
  • Thank you very much! The only question left is: `(*sizes)[i]` == `*(sizes)[i]`? If no, then, what does it mean? – vasyok03 Jan 01 '21 at 11:55
  • @vasyok03 No, it is different. And so is `*sizes[i]` (because the postfix `[i]` has a higher precedence to the prefix `*`, see https://stackoverflow.com/a/3552898/613130). – xanatos Jan 01 '21 at 12:01
  • 1
    `size_t read_size()` it is bad. Use `void` to show that the function does not take any parameters. – 0___________ Jan 01 '21 at 12:02