Home > front end >  Conditionally initialize an array
Conditionally initialize an array

Time:09-06

I want an array to have two different values, based on a condition. I can initialize the array inside the condition with the values i want.

if (myCondition == 0)
{
  byte my_message[8] = {0x00, 0xAB, 0xEE, 0xFF, 0x00, 0x01, 0x0A, 0x0B};
}
else if (myCondition == 1)
{
  byte my_message[8] = {0x11, 0xA1, 0xBC, 0x71, 0x00, 0x02, 0x94, 0x10};
}

The problem with the previous approach is that the array has local scope, and it cannot be "seen" by the code beneath.

If I try to declare the array outside the condition with:

byte my_message[8];

then, inside the condition, I cannot use the previous way of initializing the whole array all at once.

There is no pattern in the data so I can use a for loop- inside the condition- in order to give value to each element of the array easily.

Is there a way of giving values to the array, besides the cumbersome:

if (myCondition == 0)
{
  my_message[0] = {0x00}; 
  my_message[1] = {0xAB};
  my_message[2] = {0xEE};
  ....
}

CodePudding user response:

In C you can use standard function memcpy and compound literals the following way

byte my_message[8];
if (myCondition == 0)
{
  memcpy( my_message, ( byte [] ){0x00, 0xAB, 0xEE, 0xFF, 0x00, 0x01, 0x0A, 0x0B}, 8 * sizeof( byte ));
}
else if (myCondition == 1)
{
  memcpy( my_message, ( byte[] ){0x11, 0xA1, 0xBC, 0x71, 0x00, 0x02, 0x94, 0x10}, 8 * sizeof( byte ) );
}

In C it is better to use std::array instead of a raw array. For example

std::array<byte, 8>  my_message;
if (myCondition == 0)
{
  my_message = {0x00, 0xAB, 0xEE, 0xFF, 0x00, 0x01, 0x0A, 0x0B};
}
else if (myCondition == 1)
{
  my_message = {0x11, 0xA1, 0xBC, 0x71, 0x00, 0x02, 0x94, 0x10};
}

Or if to use a raw array then if the compiler supports C 20 then you can use the range based for loop the following way

byte my_message[8];

if (myCondition == 0)
{
  for ( auto *p = my_message; auto item : {0x00, 0xAB, 0xEE, 0xFF, 0x00, 0x01, 0x0A, 0x0B} )
  {
      *p   = item;
  }
}
else if (myCondition == 1)
{
  for ( auto *p = my_message; auto item : {0x11, 0xA1, 0xBC, 0x71, 0x00, 0x02, 0x94, 0x10} )
  {
      *p   = item;
  }
}

Otherwise if the compiler does not support C 20 then this declaration

auto *p = my_message;

must be moved outside the range based for loop.

CodePudding user response:

If my_message isn't changed, you could use a pointer instead of an array.

const byte my_messages[2][8] = {
   { 0x00, 0xAB, 0xEE, 0xFF, 0x00, 0x01, 0x0A, 0x0B },
   { 0x11, 0xA1, 0xBC, 0x71, 0x00, 0x02, 0x94, 0x10 },
};

const byte *my_message = my_messages[ myCondition ];

If you need to be able to change my_array, I'd use the following:

const byte my_messages[2][8] = {
   { 0x00, 0xAB, 0xEE, 0xFF, 0x00, 0x01, 0x0A, 0x0B },
   { 0x11, 0xA1, 0xBC, 0x71, 0x00, 0x02, 0x94, 0x10 },
};

byte my_message[8];
memcpy( my_message, my_messages[ myCondition ], sizeof( my_message ) );

You could memcpy from an anonymous array, but it's overly complicated and involves code repetition:

byte my_message[8];
if ( myCondition ) {
   memcpy( my_message, ( byte[] ){ 0x11, 0xA1, 0xBC, 0x71, 0x00, 0x02, 0x94, 0x10 }, sizeof( my_message) );
} else {
   memcpy( my_message, ( byte[] ){ 0x00, 0xAB, 0xEE, 0xFF, 0x00, 0x01, 0x0A, 0x0B }, sizeof( my_message) );
}

CodePudding user response:

  1. You can wrap the message into the struct and use assign operator with compound literal.
  2. You can use compound literal memcpy
typedef unsigned char byte;

typedef struct 
{
    byte my_message[8];
}message_t;

int foo(int myCondition)
{
    message_t my_message;
    if (myCondition == 0)
    {
        my_message = (message_t){0x00, 0xAB, 0xEE, 0xFF, 0x00, 0x01, 0x0A, 0x0B};
    }
    else if (myCondition == 1)
    {
        my_message = (message_t){0x11, 0xA1, 0xBC, 0x71, 0x00, 0x02, 0x94, 0x10};
    }
    return 0;
}

int bar(int myCondition)
{
    byte my_message[8];
    if (myCondition == 0)
    {
        memcpy(my_message, (byte[]){0x00, 0xAB, 0xEE, 0xFF, 0x00, 0x01, 0x0A, 0x0B}, sizeof(my_message));
    }
    else if (myCondition == 1)
    {
        memcpy(my_message, (byte[]){0x11, 0xA1, 0xBC, 0x71, 0x00, 0x02, 0x94, 0x10}, sizeof(my_message));
    }
    return 0;
}

or you can myCondition as index:

int zoo(int myCondition)
{
    byte my_message[8];
    memcpy(my_message, 
          (byte[][8]){{0x00, 0xAB, 0xEE, 0xFF, 0x00, 0x01, 0x0A, 0x0B},
                      {0x11, 0xA1, 0xBC, 0x71, 0x00, 0x02, 0x94, 0x10}}[myCondition], 
          sizeof(my_message));
    return 0;
}

memcpy way looks the most efficient:

https://godbolt.org/z/d6bMfejz5

  • Related