0

Say I have an array of unsigned char of 6 bytes.
And some function modifies value in it. How would I retrieve modified values say from 0-19bit?

void my_func()
{
   unsigned char tempVal[6] = { 0,0,0,0,0,0}
   unsigned char* temPtr = &temVal; // Say I am using pt
   int newVal;
   // call external function to modify value 
   // fun below assign new values to tempVal[0].. till tempVal[5].
   void someFuncTomodifyVal( tempPtr );     

   // Now I want values from say 1st19bits
   // how would I achieve that? I know I have to use And condtion with 7FFFF
   // so say somthing like

   newValue  =  *tempPtr & 0x7FFFF // but then *tempPtr will give me first byte only? 
}

So my question is what should I give instead of *tempPtr to get 1st 19 bits

example of

void someFuncTomodifyVal( unsigned char m[] )
{
   m[0] = 'some value retrieve from other funct'
   m[1] = ' values based on some cal'
   m[2] = ' values based on some cal'
}
samprat
  • 2,150
  • 8
  • 39
  • 73

3 Answers3

1

The main issue here is that you can't take a pointer to unsigned char and wildly cast it to a larger pointer type. This would result in a strict aliasing violation - undefined behavior. This can give incorrectly generated code and similar evil bugs.

To dodge this and access the array through a pointer, you could use a container type that contains the same type among its members:

#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <inttypes.h>

typedef union
{
  unsigned char u8 [6];
  uint32_t u32;
} my_union_t;

int main()
{
  unsigned char tempVal[6] = { 0x11,0x22,0x33,0x44,0x55,0x66};
  my_union_t* mu = (my_union_t*)tempVal;
  printf("%"PRIx32"\n", mu->u32 & 0x7FFFF);
}

As for what this will print, it depends on CPU endianess - the code is not portable. On my 32 bit little endian CPU I get 32211.

Lundin
  • 195,001
  • 40
  • 254
  • 396
-1

You probably intended to achieve something like this:

#include <stdio.h>
#include <stdint.h>

int main(void)
{
  unsigned char tempVal[6] = { 0x1,0x2,0x3,0x4,0,0 };
  uint32_t *temPtr = (uint32_t *)tempVal; // Say I am using pt
  uint32_t newVal = *temPtr;

  printf("%08x\n", newVal);
  newVal &= 0x7ffff;
  printf("%08x\n", newVal);
}

On a little endian system the output will be:

04030201
00030201

On a big endian system the output will be:

01020304
01020304

Be aware that this is not portable as it depends on the endianness of the target system and it also violates the strict aliasing rule

Portable and correct solution:

#include <stdio.h>
#include <stdint.h>

int main(void)
{
  unsigned char tempVal[6] = { 0x1,0x2,0x3,0x4,0,0 };

  uint32_t value = 0;
  for (int i = 0; i < 4; i++)
  {
    value <<= 8;
    value |= tempVal[i];
  }

  printf("%08x\n", value);
  value &= 0x7ffff;
  printf("%08x\n", value);
}
Jabberwocky
  • 48,281
  • 17
  • 65
  • 115
-2

Wrong answer

You can use a type which can store the 19 bits. Example : uint32_t *n = (uint32_t *) tempVal;. Now you can get the desired bits (*n) & 0x7FFFF


Good answer

You can use union to respect strict aliasing :

union foo {
    unsigned char   tmp[6];
    unsigned int    n;
};
Pouet_forever
  • 121
  • 1
  • 7