Why is the value in bytes displayed as 4?

Asked

Viewed 159 times

3

I am using a 2x2 matrix with a simple pointer and want to display the values of it.

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

typedef struct matriz mat;

struct matriz {

    int lin;
    int col;
    int *arr;
};

mat* cria(int lin, int col) {

    mat *m = malloc(sizeof(mat));
    m->lin = lin;
    m->col = col;
    m->arr = malloc(lin * col * sizeof(int));
    return m;
}

void exibe(mat *m) {

    for(size_t i = 0; i < sizeof(m->arr); i++) {
        printf("%3d", m->arr[i]);
    }
}
int main() {

    mat *m;
    m = cria(2, 2);
    m->arr[0] = 24;
    m->arr[1] = 16;
    m->arr[2] = 13;
    m->arr[3] = 56;

    exibe(m);

    return 0;
}

Thus sizeof(m->arr) displays 4. It should not display 16 bytes (4 x 4)?

  • I will comment here because I don’t think I have the authority to answer, but I believe the compiler will return the size of the type in which the pointer is set and not the size to which it points. That is, how it is defined as int and in its architecture this type consumes 4 bytes of memory, so the sizeof of the same will be 4. Has a discussion about it at Soen.

  • Did the answer solve your question? Do you think you can accept it? See [tour] if you don’t know how you do it. This would help a lot to indicate that the solution was useful to you. You can also vote on any question or answer you find useful on the entire site.

2 answers

3

No. What is stored in m->arr? The return of malloc(), which is a pointer. In architecture 32 bits a pointer has 4 bytes, if you want the size of the sequence, you have to pass as argument to the function. But I have the impression that this is not even the case, what you want is the amount of elements, which should also pass. Since the structure has this information, you don’t even need to pass anything, you can just use lin * col.

Actually this code seems to have other problems, but I did not investigate in depth. And the code is not creating any matrix, only a simple sequence.

  • thmm agree that it is not a matrix, since the access is done by a single index.

1

The program you want should be like this:

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

typedef struct matriz mat;

struct matriz {
    int lin;
    int col;
    int *arr;
};

mat* cria(int lin, int col) {
    mat *m = malloc(sizeof(mat));
    m->lin = lin;
    m->col = col;
    m->arr = malloc(lin * col * sizeof(int));
    return m;
}

void destroi(mat *m) {
    if (m == NULL) return;
    free(m->arr);
    free(m);
}

int ler_elemento(mat *m, int i, int j) {
    return m[i * m->col + j];
}

int definir_elemento(mat *m, int i, int j, int valor) {
    m[i * m->col + j] = valor;
}

void exibe(mat *m) {
    for (int i = 0; i < m->lin; i++) {
        for (int j = 0; j < m->col; j++) {
            printf("%3d ", ler_elemento(m, i, j));
        }
        printf("\n");
    }
}

int main() {
    mat *m;
    m = cria(2, 2);
    definir_elemento(m, 0, 0, 24);
    definir_elemento(m, 0, 1, 16);
    definir_elemento(m, 1, 0, 13);
    definir_elemento(m, 1, 1, 56);

    exibe(m);
    destroi(m);

    return 0;
}

Note that I created the functions ler_elemento and definir_elemento to centralize, abstract and encapsulate the logic of accessing the elements in the correct positions. This way, the other parts of the code don’t have to worry about the more complicated details of how to find the correct position in the array of matrix elements and won’t even have to worry about knowing the structure mat has an array inside. With that, if later you want to change the way the structure mat organises your data, only functions ler_elemento, definir_elemento and cria will need to be changed, which avoids cascading changes, where changing a small detail would force the need to promote major changes in the whole code.

I also added a function to de-locate the mat. It is good practice to always dislocate what you allocate, and therefore, whenever you have a function that creates something through dynamic memory allocation, you should already immediately have the hand function that dislodges that same thing.

As to the sizeof(m->arr), That will give you the size of the pointer m->arr instead of the matrix size. Note that arr is the type int *, and therefore sizeof(m->arr) is the same as sizeof(int *). The result is 4 because an integer pointer occupies 4 bytes on your computer, no matter where that pointer points or even if it points to a valid memory address.

The purpose of sizeof is to measure how much memory static a certain structure occupies, and it is determined at compilation time, not execution. For dynamic memory allocation, the size of the allocated data depends on information that is only available at runtime, and therefore there is no way the compiler knows which one it would be. The solution is you calculate the size yourself if you need to, and at the end of the day, you don’t need it to just display the matrix on the screen.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.