verendra
verendra

Reputation: 223

Char array to unsigned short conversion issue

I am trying to convert char array to unsigned short but its not working as it should.

char szASCbuf[64] = "123456789123456789123456789";

int StoreToFlash(char szASCbuf[], int StartAddress)
{   
int iCtr;
int ErrorCode = 0;
int address = StartAddress;
unsigned short *us_Buf = (unsigned short*)szASCbuf;         

// Write to flash
for(iCtr=0;iCtr<28;iCtr++)
{   
    ErrorCode = Flash_Write(address++, us_Buf[iCtr]);
    if((ErrorCode &0x45)!= 0)
    {
      Flash_ClearError();          
    }
}
return ErrorCode;
}

When I see the Conversion, on us_Buf[0] I have value 12594, us_Buf[1]= 13108 like that and I have values only uptous_Buf[5]` after that it is "0" all remaining address. I have tried to declare char array like this also

char szASCbuf[64] = {'1','2','3','4','5','6','7','8','9','1',.....'\0'};

I am passing the parameters to function like this

StoreToFlash(szASCbuf, FlashPointer); //Flashpointe=0

I am using IAR embedded workbench for ARM. Big enedian 32. Any suggestions where i am doing wrong?

Thanks in advance.

Upvotes: 0

Views: 1366

Answers (2)

Blagovest Buyukliev
Blagovest Buyukliev

Reputation: 43558

Reinterpreting the char array szASCbuf as an array of short is not safe because of alignment issues. The char type has the least strict alignment requirements and short is usually stricter. This means that szAscBuf might start at address 13, whereas a short should start at either 12 or 14.

This also violates the strict aliasing rule, since szAscBuf and us_Buf are pointing at the same location while having different pointer types. The compiler might perform optimisations which don't take this into account and this could manifest in some very nasty bugs.

The correct way to write this code is to iterate over the original szASCBuf with a step of 2 and then do some bit-twiddling to produce a 2-byte value out of it:

for (size_t i = 0; i < sizeof(szAscbuf); i += 2) {
    uint16_t value = (szAscbuf[i] << 8) | szAscbuf[i + 1];
    ErrorCode = Flash_Write(address++, value);

    if (ErrorCode & 0x45) {
        Flash_ClearError();          
    }
}

If you really intended to treat the digit characters with their numeric value, this will do it:

uint16_t value = (szAscbuf[i] - '0') + (szAscbuf[i + 1] - '0');

In case you just want the numeric value of each character in a 2-byte value (1, 2, 3, 4, ...), iterate over the array with a step of 1 and fetch it this way:

uint16_t value = szAscbuf[i] - '0';

Upvotes: 2

Serge Ballesta
Serge Ballesta

Reputation: 149155

That's normal !

Your char array is "123456789123456789123456789" or {'1','2','3','4','5','6','7','8','9','1',.....'\0'}

But in ASCII '1' is 0x31, so when you read the array as a short * on a big endian architecture, it gives :

{ 0x3132, 0x3334, ... }

say differently in decimal :

{ 12594, 13108, ... }

Upvotes: 0

Related Questions