0

In the main function, I just declare double pointer variables and assign 2 dimensional matrix as below.

int main(){
double **XNODE;
XNODE = (double**)calloc(2,sizeof(double*));
for(int i=0; i<2; i++){
XNODE[i] = (double*)calloc(3,sizeof(double));
}
XNODE[0][0] = 1.0; XNODE[0][1] = -1.0; XNODE[0][2] = -122.0;
XNODE[1][0] = 2.0; XNODE[1][1] = 3.0; XNODE[1][2] = -4.0;

test(*XNODE);
return 0;

and then put the XNODE variable in the below "test" function

void test(double*XNODE)
{
for(int i=0; i<2; i++){
for(int j=0; j<3; j++){
printf("%e ", *(XNODE+3*i+j));
}
}

My expectation is 1 -1 -122 2 3 -4

However the output is as below 1 -1 -122 1.63e-322 2 3

How can I fix this problem??

Song
  • 13
  • 3
  • 2
    Realizing the `test` function expects it's data in contiguous memory rather than three distinct allocations, as it is computing offsets of row vs. column all on its own would probably be beneficial. – WhozCraig Dec 27 '22 at 12:19
  • I can't understand your comment. Could you please explain more detail? – Song Dec 27 '22 at 12:21
  • you are passing `double **` but test expects `double *` – stark Dec 27 '22 at 12:21
  • 1
    See [**Correctly allocating multi-dimensional arrays**](https://stackoverflow.com/questions/42094465/correctly-allocating-multi-dimensional-arrays). Whoever taught you that you can make a "2-d array" from a double pointer and looping calls to `malloc()` was wrong. You've created a pointer to an array of pointers to individual and separate 1-dimensional arrays. That's not in any way a two-dimensional array. Note that some benighted compilers stuck in the pre-C99 last century don't support creating dynamic arrays in that manner. – Andrew Henle Dec 27 '22 at 12:22
  • 1
    Please indent your code for your own sake. – Jabberwocky Dec 27 '22 at 12:35
  • @stark [you are passing double ** but test expects double *](https://stackoverflow.com/questions/74929139/language-c-double-pointer-variable-in-function/74930198#comment132228240_74929139): Code is passing a `double *` with `test(*XNODE);`, not a `double **`. – chux - Reinstate Monica Dec 27 '22 at 13:59
  • @Song Best to post true true code and exact output. `printf("%e ", *(XNODE+3*i+j));` did not print `1 -1 -122 1.63e-322 2 3`. – chux - Reinstate Monica Dec 27 '22 at 14:06
  • @AndrewHenle: Re “That's not in any way a two-dimensional array”: Do not go overboard in your pronouncements. There is a way in which that is a two-dimensional array. Arrays existed as a mathematical entity long before modern computers existed. Putting elements contiguously in memory, and putting rows of such elements contiguously in memory, is only one way of implementing an array. Arrays can be implemented in other ways, including using pointers to rows of elements, hashes, or trees of various kinds. Implementing a massively sparse array solely with contiguous elements would be foolish. – Eric Postpischil Dec 27 '22 at 14:08
  • 1
    @EricPostpischil A double pointer that references a one-dimensional array of pointers that each reference individual and separate one-dimensional arrays is not compatible with [multidimensional arrays as defined by the C standard](https://port70.net/~nsz/c/c11/n1570.html#6.5.2.1p3). C is hard enough for beginners to get right without adding needless confusion with academic definitions of objects that don't match the standard definition. This very question is evidence of that. – Andrew Henle Dec 27 '22 at 14:25
  • @AndrewHenle: My comment does not say that the pointer arrangement is compatible with multidimensional arrays as described by the C standard, and your first comment does not say that the pointer arrangement is not a two-dimensional array as described by the C standard. Your first comment says the pointer arrangement is “**not in any way** a two-dimensional array.” That is false. There is a way in which it is a two-dimensional array, and human beings are not compelled to use only the C standard’s terminology when talking about their programs. Your pronouncement is too broad. – Eric Postpischil Dec 27 '22 at 14:35

2 Answers2

0

test(*XNODE); passes the pointer saved in XNODE[0]. That pointer's value was from the allocation when (i==0) and XNODE[i] = (double*)calloc(3,sizeof(double));. That allocation has memory for 3 double.

test() attempts to print 6 adjacent double. The first 3 are as expected. The rest are outside the allocation and so undefined behavior (UB).

How can I fix this problem??

  • Rewrite test() to test(int rows, int cols, double **d).

  • Re-write test() body to use rows, cols, d.

  • Pass test(2, 3, XNODE).

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
0

The code inside the function, *(XNODE+3*i+j), expects to be able to calculate the location of any array element as an offset from the base pointer, XNODE. To do this, all of the array elements must be in memory consecutively after the start of the array.

The allocations in main do not do this. The loop allocates memory for each row separately, so each row is wherever the calloc routine puts it. They are unlikely to be consecutively in memory.

To allocate memory correctly, you must allocate all of the memory for the elements of the array in one allocation. Calculate that amount of memory, allocate it, and pass the pointer to that memory to test. You can do this with double *XNode = calloc(2 * 3 * sizeof *XNode);.

To access that memory, you can do it the same way the code in test does: The element in row i, column j is *(XNode + 3*i + j). This can also be written XNode[3*i + j].

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312