1

I realized the following problem:

struct S{
   double **A;
 }
 struct S s;
 s.A = (double **) malloc(sizeof(double*)*2);
 s.A[0] = (double *) malloc(sizeof(double)*3);
 s.A[1] = (double *) malloc(sizeof(double)*3);

Now let us say I want to do pointer arithmetic of s.A. If I start by defining a pointer to a double like:

double ptr
ptr = &s.A[0][0];

I will expect that

*(ptr+1) is equivalent to s.A[0][1]

*(ptr+2) is equivalent to s.A[0][2]

*(ptr+3) is equivalent to s.A[1][0]

I realize that *(ptr+3) is NOT equivalent to s.A[1][0] and points to a wrong address. To point to s.A[1][0] I need to do *(ptr+4), so jumping with 1. Can anyone explain why I need to jump an extra one when I want to begin at the next row, and how will I do it if I had to start at the third, fourth etc rows?

ATK
  • 1,296
  • 10
  • 26
  • Use `s.A = malloc(sizeof(*(s.A))*2)` instead – klutt Jun 01 '20 at 08:37
  • would that help? – ATK Jun 01 '20 at 08:38
  • Not with your actual problem, but it is so much better. https://stackoverflow.com/q/605845/6699433 – klutt Jun 01 '20 at 08:39
  • What you create is a so-called [*jagged* array](https://en.wikipedia.org/wiki/Jagged_array). For a "true" 2D array, (like `double a[2][3];`) you have to remember that it's actually an array of arrays, and what you have is a 1D array of pointers. You can solve it by creating an array of `2 * 3` elements, and through some extra arithmetic treat it as a 2D array of arrays. – Some programmer dude Jun 01 '20 at 08:42
  • Thanks very much for the thread and the advice. Appreciate it. – ATK Jun 01 '20 at 08:43
  • @Someprogrammerdude, Is it because it is a member of a struct. Although, in my real application I would need to keep my 2D array as part of the struct. So how it that be possible – ATK Jun 01 '20 at 08:44
  • As for `ptr = &s.A[0][0]`, that makes `ptr` be a pointer to the first element of `s.A[0]` only. Because `s.A` is an array of pointers, there's really no relation to `s.A[1]` at all. – Some programmer dude Jun 01 '20 at 08:45
  • No it doesn't matter that it's a structure member, that is totally irrelevant. The problem is the nature of your "arrays": You have an array of two unrelated pointers. – Some programmer dude Jun 01 '20 at 08:47
  • Really? So if you needed to have an array such as `s.A` being contigous to do better chache utilisation and vectorisation etc, this is all not really possible? – ATK Jun 01 '20 at 08:47
  • Now I get what you mean, so how would I I dynamically allocate such a truly 2D array? I though you could only do this with double pointers in C – ATK Jun 01 '20 at 08:48
  • Like I said previously, allocate a single array of `M * N` elements, where `M` is the number of "rows" and `N` is the number of columns. In your case it would be `2 * 3`. So `malloc(sizeof(double) * 2 * 3)` to create a single contiguous array of elements. – Some programmer dude Jun 01 '20 at 08:49
  • On another note, please don't use explicit pointer arithmetic. For any pointer *or array* `p` and index `i`, the expression `*(p + i)` is *exactly* equal to `p[i]`. The latter (`p[i]`) is usually easier to read and understand, and less to write as well. – Some programmer dude Jun 01 '20 at 08:51
  • Ahh, okay. And the compiler would be able to cope with for example accesssing the array like a 2D array, such as `s.A[0][2] ` – ATK Jun 01 '20 at 08:51
  • Not if you have a single array allocation. Then you need to do some extra arithmetic to get the correct index. You could easily find out yourself with the help of a pen and some paper, or find one of the several thousands examples that exists all over the Internet. – Some programmer dude Jun 01 '20 at 08:56
  • I get the feeling that you're trying to write "clever" code that will come and bite you in the future. ;) – klutt Jun 01 '20 at 08:57

1 Answers1

2

when you allocate the pointers at:

s.A[0] = (double *) malloc(sizeof(double)*3);
s.A[1] = (double *) malloc(sizeof(double)*3); 

you get what addresses the operating system gives you. Not like an array, it doesn't have to be consecutive.

Bizi-byte
  • 36
  • 2