1

So I got an assignment in school that includes 3 strix (int ***) I need to write some int values into "pointers", but I get an error when I attempt to do so. Here's my code:

void main()
{
    unsigned int size, i;
    int arr[SIZE];
    int ** pointers;
    int ascend_flag;

    printf("Please enter the number of items:\n");
    scanf("%u", &size);
    for (i = 0; i < size; i++)
        scanf("%d", &arr[i]);
    scanf("%d", &ascend_flag);

    pointerSort(arr, size, (char)ascend_flag, &pointers);
    printf("The sorted array:\n"); //Print the sorted array
    printPointers(pointers, size);
    free(pointers);
}

void pointerSort(int* arr, unsigned int size, char ascend_flag,
        int *** pointers)
{
    int i, j;

    pointers = (int ***) malloc(size * sizeof(int **));
    for (i = 0; i < size; i++)
    {
        ***(pointers+i) = *&arr[i];
    }

    mergeSort(*pointers, size);

    if (ascend_flag == 0)
    {
        for (i = 0, j = size - 1; i < (size / 2); i++, j--)
        {
            swapInArr(**(pointers + i), **(pointers + j));
        }
    }
}

The debugger shows that that the error occurs in this loop:

 for (i = 0; i < size; i++)
 {
     ***(pointers+i) = *&arr[i];
 }

Specifically, I keep getting this error:

Exception thrown at 0x0127192A in Project3.exe: 0xC0000005: Access violation reading location 0xCDCDCDCD.

If there is a handler for this exception, the program may be safely continued

I acknowledge that the program is incomplete, and it may be flawed in ways unrelated to the error I'm getting. Please focus on issues related to the access violation error.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
AmitBL
  • 89
  • 4
  • 12
  • You can store `int` values indirectly *via* pointers into `int` objects, which is what I suppose you want to do, but it's important to understand that that's quite a different thing from storing anything *in* a pointer. – John Bollinger Mar 29 '17 at 13:39
  • The school shouldn't teach you crap like this. Ignore the assignment. Feel free to provide a link to this site, I'll be happy to call your teacher incompetent to their face. As a rule of thumb, whenever your program has more than two levels of indirection, it is a certain indication of poor program design. This is commonly known as "tree star programming" which is a derogatory term used for "clueless programmers who don't know what they are doing and make their programs needlessly complicated". – Lundin Mar 29 '17 at 13:44
  • As for allocating arrays in this manner to emulate multi-dimensional arrays, it is also bad and incorrect practice. See [Correctly allocating multi-dimensional arrays](http://stackoverflow.com/questions/42094465/correctly-allocating-multi-dimensional-arrays) – Lundin Mar 29 '17 at 13:44
  • I hate three stars, but Teacher is making us do it so I can't change it. – AmitBL Mar 29 '17 at 13:48
  • @Lundin is it a multi-dimensional array or merely an array of pointers that is passed in by reference? – Chris Turner Mar 29 '17 at 13:49
  • @ChrisTurner It is an array of pointers, see the link I posted. – Lundin Mar 29 '17 at 13:53
  • Seems we need a "bad-teacher" tag. – Jabberwocky Mar 29 '17 at 13:54
  • @ChrisTurner, it is in no way a multi-dimensional array or a pointer to one. It may be intended as a pointer to an array of pointers meant to be used similarly to a 2D array, but that's a different thing. – John Bollinger Mar 29 '17 at 13:54
  • 1
    @AmitBL, I'm inclined to suspect that you're missing the point of the assignment. I infer that you're supposed to be creating a bunch of pointers into the array, sorting those based on the pointed-to values, and providing a pointer to them back to the program. In that case, copying the `int` values is precisely the wrong thing to do. – John Bollinger Mar 29 '17 at 13:59
  • @JohnBollinger that's basically my reasoning behind my answer – Chris Turner Mar 29 '17 at 14:07
  • 1
    @Lundin: teaching sometimes includes showing a bad path and explaining why it is bad... We know that three star is normaly the evidence of a design problem, but OP really needs to understand what indirection, allocation, dereference an deallocation mean, because seeing his code he has not fully understood it ;-) – Serge Ballesta Mar 29 '17 at 14:08
  • BTW in C **do not cast malloc**! – Serge Ballesta Mar 29 '17 at 14:08

1 Answers1

3
pointers = (int***)malloc(size * sizeof(int**));

The above statement is allocating a block of memory and assigning it to pointers which can be used like an array like pointers[0] or like pointers+0.

***(pointers+i) = *&arr[i]; is the same as **(pointers[i]) = *&arr[i];

The problem here is that pointers[i] is an int ** and not yet pointing at any location in memory so you can't dereference it once, let alone twice.

If what you're trying to do is create an array of pointers to members of arr then your code should look more like this.

(*pointers) = (int**)malloc(size * sizeof(int*));  
for (i = 0; i < size; i++) 
{
    (*pointers)[i] = &(arr[i]);      
}

And because you want to return pointers to the calling function you pass it in as a pointer and have to de-reference it.

Chris Turner
  • 8,082
  • 1
  • 14
  • 18
  • 2
    It is also worth noting that `*&arr[i]` is equivalent to just `arr[i]`, so `***(pointers+i) = *&arr[i]` is even more cleanly expressed as `**(pointers[i]) = arr[i]`. – John Bollinger Mar 29 '17 at 14:05
  • Could eliminate some unneeded `**`and `()` by dropping the cast: `*pointers = malloc(size * sizeof(int*));` or `*pointers = malloc(sizeof *(*pointers) *size);` – chux - Reinstate Monica Mar 29 '17 at 14:18
  • @chux yes, the cast isn't needed, but I left it in so to keep the code looking similar to the original – Chris Turner Mar 29 '17 at 14:22
  • Can anyone explain in more detail the difference between (*pointer)[i] and *pointer[i]? – AmitBL Mar 30 '17 at 20:34
  • @AmitBL it boils down to operator precedence - `[]` have higher precedence over `*` (dereference), so the second way ends up with you getting `pointer[i]` and then dereferencing it. The first way however, cos of the brackets, means you first do the dereferencing and then get `[i]`. Which is what you want in this case as `pointers` in the function is a pointer to your `pointers` from `main`. – Chris Turner Mar 31 '17 at 08:54