4

Here's my code:

#include <stdlib.h> //malloc

#define lineSize 16
#define columnSize 16
#define cellSize 16

int main()
{
    unsigned char*** tab;
    tab = malloc(sizeof(unsigned char**) * lineSize);
    for(unsigned int i = 0; i < lineSize; i++)
        tab[i] = malloc(sizeof(unsigned char*) * columnSize);
    for(unsigned int i = 0; i < lineSize; i++)
        for(unsigned int j = 0; j < columnSize; j++)
            tab[i][j] = malloc(sizeof(unsigned char) * cellSize);


    unsigned int line = 0;
    unsigned int column = 0;
    unsigned int cell = 0;

    unsigned char* ptr = &tab[line][column][cell];

    for(line = 0; line < lineSize; line++)
        for(column = 0; column < columnSize; column++)
            for(cell = 0; cell < cellSize; cell++)
                *ptr = ...;

    return 0;
}

This code fills tab with values that are only known at execution time

In this case there's no much problems because lineSize, columnSize and cellSize are small, The problem is that when cellSize become 100000+ then dereferencing the pointer gets expensive in terms of time, that's why I thought to use a pointer to avoid dereferencing.

The problem is that I don't know how to do in order for the pointer to be updated as line, column or cell change.

Appreciates your help, Thanks.

EDIT: More explanations:


The bigger lineSize, columnSize and cellSize, the longer is the execution. It's expected but what takes a "lot of time" is what's inside the loops and inside the loops is a pointer dereferencing 16*16*100000 times (When cellSize = 100000).

If I'm right, Dereferencing is a multiplication like:

tab[2][5][3] = tab + 2*16*100000 + 5*100000 + 3;

And do math like that 16*16*100000 times is long.

So to avoid maths, I thought about a pointer that permanently points totab[line][column][cell] but I don't know how to do it without having to recalculate the pointer each time cell is incremented.

Tom Clabault
  • 481
  • 4
  • 18
  • Why are you not moving the determination of the address (i.e. writing to pointer variable) into the loop? If you access several times via that pointer it is saving time. If you are not, then introducing the pointer is a step in the wrong direction. Just access `tab[line][column][cell]` directly, once or twice. – Yunnosch Aug 26 '17 at 19:58
  • @Yunnosch Moving the determination of the addres of the pointer directly into the loop will not help. It will do the exact same amount of calcs as if I was just using `tab[line][column][cell]` – Tom Clabault Aug 26 '17 at 20:03
  • That is only true for a single access. Actually it is more costly for first storing the pointer. So as I said, a step in the wrong direction. – Yunnosch Aug 26 '17 at 20:05
  • You can take the risky way, i.e. increase the pointer by the difference (according to your somewhat appropriate math). But, there be dragons. – Yunnosch Aug 26 '17 at 20:06
  • @Yunnosch I'll test that – Tom Clabault Aug 26 '17 at 20:07
  • What is ptr = .... – 0___________ Aug 26 '17 at 20:08
  • Cache is king. You should spend some time reading about that ... though you shouldn't *always* use every technique. – o11c Aug 26 '17 at 20:10
  • I'm not sure I quite understand what exactly the problem - is it the posted triple nested loop (which I assume is for initialization) taking up too much time? Or is it the above part which allocates the memory? Or is it accessing the data using its index after it being stored in a matrix? – Luke Aug 26 '17 at 20:10
  • @PeterJ_01 ... is a value only known at execution time, that's what I didn't write it on the post, we don't know what it is. Just think about it as a value – Tom Clabault Aug 26 '17 at 20:10
  • @Tom Clabault You do not understand. You assign the pointer outside the loop. So you write to the same location `linesize*columnsize*cellsize` times? It does not make too much sense – 0___________ Aug 26 '17 at 20:13
  • Related question: Since all the sizes are fixed, why are you even using `malloc`? Why don't you simply do `unsigned char tab[16][16][16];`? – vgru Aug 26 '17 at 20:16
  • Stack `100000*100000*100000` bytes? – 0___________ Aug 26 '17 at 20:17
  • Anyway your &tab[line][column][cell]; is wrong – 0___________ Aug 26 '17 at 20:17
  • @PeterJ_01 I don't want to write to the same location lineSize * columnSiize * cellSize times, and that's the problem. I want the pointer to be auto-updated. – Tom Clabault Aug 26 '17 at 20:20
  • @Groo with 16*16*16 it's ok, but with 16*16*100000, the stack will explode :) – Tom Clabault Aug 26 '17 at 20:21
  • @PeterJ_01 Why is my `&tab[line][column][cell]` wrong ? Doesn't it take the adress of `tab[line][column][cell]` ? – Tom Clabault Aug 26 '17 at 20:22
  • @TomClabault: the question is whether the size is fixed at compile time. Stack isn't the only place you can place an array. – vgru Aug 26 '17 at 20:28
  • @Groo No, the size is not fixed at compile time. We don't the size in advanced except that only cellSize changes, lineSize and columnSize are always 16 – Tom Clabault Aug 26 '17 at 20:29

2 Answers2

3

With a 3-D array, you can't move a pointer to a new position except for the last dimension. You can move ptr along the cell dimension, but not along the other dimensions.

To do that, just add the distance:

ptr2 = ptr + dist

The calculations you mention in the edit are not the same as dereferencing, they are used when you interpret a 1-D array as a 3-D array. This would allow to move along all dimensions.


You could do the following:

for(line = 0; line < lineSize; line++) {
    unsigned char** my_line = tab[line];
    for(column = 0; column < columnSize; column++)
        unsigned char* my_col = my_line[column];
        for(cell = 0; cell < cellSize; cell++)
            unsigned char data = my_col[cell];
alain
  • 11,939
  • 2
  • 31
  • 51
-1

You have the UB in your code.

tab[line][column][cell]; 

does not work with individually malloc-ed values. It only works with the arrays which are continuous chunks of memory accommodating all the table elements. Your chunks may be anywhere in the memory.

0___________
  • 60,014
  • 4
  • 34
  • 74
  • 2
    It's not that `tab[line][column][cell]` doesn't work, it's the problem that you cannot do this "at the top" and then advance the pointer around like it's a contiguous block. (not my downvote though, I understand what you're saying, but I think the first sentence might be confusing to people) – vgru Aug 26 '17 at 20:37