0

I have a function for what I pass a matrix and a variable as a pointer (I simplified it, maybe in this form it doesn't make sense, but I didn't want to paste the whole code :)

uint64_t returndata = 0;
uint32_t binary_lock = 0;

void initLamp(uint8_t time, const uint8_t *datatable, uint64_t *outdata)
{
    for(uint8_t k = 0; k < ROW; k++)
    {
        if(*(datatable + k * COLS) == time)
        {
            binary_lock |= (1 << k);
        }
    }
    for(uint8_t i = 0; i < ROW; i++)
    {
        *outdata |= (1 << (3 * i));
    }
}

I have another file, called datafield.h, what consists the matrix:

static const uint8_t signal_table[][COLS] =
{        
    {22, 24, 63, 67}, // 1A
    {87, 89, 31, 35}, // 1B
    {0 ,  2, 21, 24}, // 1C
    {0 ,  3, 22, 43}, // 1D
}

In the main I need to refer to the function like this, to avoid errors and warnings:

int main(void)
{
    initLamp(0, *signal_table, &returndata);
}

The question is: I'm a bit sceptic using the main function. I'm almost sure that the usage of '&returndata' is correct, but why do I have to put the '*' operator before the 'signal_table'. I thought I would only need to give the address of the matrix like &signal_table, but with this it is not working.

2
  • 2
    signal_table is of type const uint8_t [4][4]. As an operand of unary *, signal_table is converted from const uint8_t [4][4] to const uint8_t (*)[4] (pointer to array length 4 of const uint8_t), so *signal_table is of type const uint8_t [4]. As a function call argument, *signal_table is converted from const uint8_t [4] to const uint8_t *, which is compatible with the function parameter. It would be more natural to replace *signal_table with &signal_table[0][0], which is also of type const uint8_t * and points to the same thing. Commented Nov 23, 2021 at 13:27
  • 1
    In general, using pointer arithmetic on a pointer to some element to access an element in a different row of a 2-D array (treating a 2-D array as a flat 1-D array) leads to undefined behavior. There is an exception for pointer to character types (char, signed char, unsigned char) which can legitimately be used to access any byte of the 2-D array. It is possible that uint8_t is not defined as a character type on some C implementation (it could be defined as an extended integer type), which would disallow this usage. If uint8_t is the same type as unsigned char then it is OK. Commented Nov 23, 2021 at 14:45

1 Answer 1

2

Avoid writing needlessly obscure or complicated code when you could keep it simple. Your function should probably be written as:

void initLamp(uint8_t time, const uint8_t datatable[ROWS][COLS], uint64_t *outdata)

Or alternatively with VLA syntax:

void initLamp(uint8_t time, 
              size_t rows, 
              size_t cols, 
              const uint8_t datatable[rows][cols], 
              uint64_t *outdata)

In case of the latter, call it as:

initLamp(0, ROWS, COLS, signal_table, &returndata);

And the for loops should be simplified to use array syntax:

for(size_t r = 0; r < rows; r++)
{
  for(size_t c = 0; c < cols; c++)
  {
    datatable[r][c] = something;
  }
}

Another issue is the 1 << ... parts of your code, which are likely hidden bugs. 1 is an integer constant of type int. You might end up shifting data into the sign bit which is an undefined behavior bug. In case of uint64_t you should rather be using 1ULL or (uint64_t)1.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the tip, especially for the hidden bug, since I was struggling with it for some minutes.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.