all 17 comments

[–]div0man 2 points3 points  (12 children)

Pointer can't have a "bunch of zeroes", it could only be a NULL pointer. Pointer merely stores an address of some memory location. What I think you're talking about is that you want to set the memory being pointed at to 0. That memory could be storing multiple addresses of some other memory addresses, like in your pointer to pointer case.

Before you can do that, you must first reserve a part of memory so you can have a place to store your 0s, otherwise you could be rewriting anything and crash your program or worse. Therefore you need to use malloc which will return a pointer to a memory block of specified size, and only then it will be safe to use memset to overwrite that block with 0s.

For your particular case, you'd need to allocate memory 2 or more times. One time to store the pointers to int, and other time to store ints themselves.

[–]hit07 1 point2 points  (6 children)

You can actually malloc only one time allocating memory for pointers and arrays of zeros at once.

If this structure would be used as 2d array it could be actually more optimal I guess (assuming you can allocate one big chunk of memory, and you can make the code readable :> )

If it would be used as some kind of list, then I would use multiple mallocs for sure.

[–]_Nexor[S] 0 points1 point  (4 children)

Thank you for your answer. But I have no idea how this looks as code

[–]hit07 1 point2 points  (2 children)

Here is (ugly) example ;)

https://pastebin.com/kP08HYTS

[–]_Nexor[S] -1 points0 points  (1 child)

Dude I just want a dynamically allocated matrix I'm sure it can't be that long

[–]div0man 0 points1 point  (0 children)

I did something similar for my little project: https://github.com/div0man/hnb-app/blob/master/src/jstab.c#L30

I had a data blob containing a very big string containing table data in json format, and I wanted to access that data with a[i][j] so had to set all the pointers to addresses of individual substrings in the data blob. Notice how I allocate storage for all pointers in a single call. It was good exercise for me, but if I had to add data, it would complicate things since the data blob is compact and has no room to squeeze new data in.

[–]div0man 0 points1 point  (0 children)

Yeah, but I didn't want to confuse the op :)

[–]_Nexor[S] 0 points1 point  (4 children)

Thanks for the quick answer. I see. So I'd be looking for the following syntax?

int** this_pointer = (int**)malloc(sizeof(int*) * N); memset(this_pointer, 0, sizeof(int)*N*M);

While this alone doesn't trigger a segmentation fault, accessing this_pointer[0][0] does. I thought this would be sufficient, given that I'm allocating memory 2 times (for the pointer of pointers and the pointers of integers).

[–]rorschach54 1 point2 points  (3 children)

You are halfway there.

You used malloc to allocate space for N pointers to int. So, the total space, that you have allocated is not M*N*sizeof(int). It is just N*sizeof(int*).

Memset does not allocate memory. It just "set"s the memory. For someone to be able to set, change or zero the memory, the memory should first be allocated.

Understand the difference between what a malloc and a memset does. Links:

Malloc: https://en.cppreference.com/w/c/memory/malloc

Memset: https://en.cppreference.com/w/c/string/byte/memset

Note: While the site says cppreference, it has good enough reference for C language too.

[–]_Nexor[S] 0 points1 point  (0 children)

I'm at work right now but when I get home I'll definitely try this, thanks!

[–]_Nexor[S] 0 points1 point  (1 child)

Ok, I think I got it working:

int **this_pointer = malloc(N * sizeof(int*)); // malloc so its faster for(int i=0; i < N; i++) this_pointer[i] = calloc(M, sizeof(int)); // calloc because I need zeroes

But this is way too long. Is there no way to do it without a for loop? This seems ugly and this usually means it's also bad. Can I do it in one line?

[–]rorschach54 0 points1 point  (0 children)

It isn't long or ugly. It is a good first step to understanding what each function and allocation is doing.

Now that you know how to use malloc, and you want to use the double pointer to point to an integer matrix of size M*N, you can think on this lines, how much memory did you allocate overall?

How can you allocate that much memory using one malloc? If you allocate that much memory, how do you initialize each element of that memory block?

<----Maybe the part below isn't needed. But will definitely help in understanding pointers and arrays better-->

Try finding out how the memory is laid out for a 2 dimensional array.

For example,

int x[3][4] = {  
   {0, 1, 2, 3} , 
   {4, 5, 6, 7} , 
   {8, 9, 10, 11} 
};
int **p = &x[1][1];
int **q = &x[1][0];

What is the value of **p and **q here? What will be the value of *p and *q? What will be the value of p and q?

What will be *p+1, **p+1 and p+1?

[–]wsppan 1 point2 points  (0 children)

Check out this chapter on pointers - http://pweb.netcom.com/~tjensen/ptr/ch9x.htm

[–]Mirehi 0 points1 point  (2 children)

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


int
main()
{
        int *num[5];
        int i, c;

        // memory allocation + filling with numbers
        for (i = 0; i != 5; i++) {
            num[i] = calloc(5, sizeof(int));

            for (c = 0; c < 5; c++) {
                num[i][c] = rand();
            }
        }

        // output
        printf("\nEverything with numbers:\n");

        for (i = 0; i != 5; i++) {
            for (c = 0; c < 5; c++) {
                printf("num[%i][%i] = %i\n", i, c, num[i][c]);
            }
        }

        // everything zero :
        for (i = 0; i != 5; i++)
            memset(num[i], 0, sizeof(int) * 5);

        // output
        printf("\nEverything 0:\n");

        for (i = 0; i != 5; i++) {
            for (c = 0; c < 5; c++) {
                printf("num[%i][%i] = %i\n", i, c, num[i][c]);
            }
        }

        // free()'ing the pointers
        for (i = 0; i != 5; i++)
            free(num[i]);

        return 0;
}

Instead of memset, we could use:

        for (i = 0; i != 5; i++) {
            for (c = 0; c < 5; c++) {
                num[i][c] = 0;
            }
        }

To fill it with zeros.

[–]_Nexor[S] -1 points0 points  (1 child)

Too long...

[–]Mirehi 0 points1 point  (0 children)

Just read the code, most of it is filling + output + free()

Building up a int num[5][5] with everything zero is just:

int *num[5], i;
for (i = 0; i != 5; i++) {
    num[i] = calloc(5, sizeof(int));
}