# Calculating CheckSum

• 01-15-2011
drkidd22
Calculating CheckSum
Hello,

I'm trying to calculate the checksum of a string by adding all characters and then using ones complement on the addition result, this is what I've done so far.

Code:

```int main(short argc, char **argv) {   unsigned char serNum [] = "DS0008D-0111A";   unsigned short checksum;   checksum = CalcChksum(serNum, 13);   cout << hex << checksum << "\n" << "\n"; //Here I get only the first byte 2B on the output, should be FD 2B; } unsigned short CalcChksum(unsigned char *start_addr, int bytecnt) {   int i;   unsigned short chksum;   chksum = 0;   // Calculate 1's complement chksum   for(i=0; i<bytecnt; i++)       chksum+= (unsigned short)*(start_addr+i);   chksum = (char)~chksum;   return(chksum); }```
If there is an easier method or better way of doing this I would appreciate any help
• 01-15-2011
modwind
You're using type conversions incorrectly:
Code:

`chksum+= (unsigned short)*(start_addr+i);`
(unsigned short) is not needed here.
Code:

`chksum = (char)~chksum;`
(char) truncates your checksum from 2 bytes to 1. If you remove it, you'll get FD 2B.

Also the checksum finding method doesn't use symbol positions in calculation. It can be not reliable enough, but it depends on the purpose.
• 01-15-2011
drkidd22
Thanks, that really helped, specially the
Code:

`chksum = (char)~chksum;`
line, can't believe I missed that.

I don't really get what you mean with
Code:

`chksum+= (unsigned short)*(start_addr+i);`
should I just add the bytes with no conversion?

what do you mean by symbol positions in calculation, I want to make this as reliable as I can as it may be used on a DLL file.
• 01-15-2011
modwind
You should use conversion only when target type can contain smaller amount of data (assignment of "short" to "char" for example).

By position I mean that "DS0008D-0111A", "DS0080D-0111A" will give the same sum.
To get something more reliable, CRC-16 could be used.
• 01-15-2011
drkidd22
Ok, I understand now. This was the requirement I was given, just sum and do the 1's complement. We use CRC-16 for other stuff, but I'm just sticking with what I was given for now.

• 01-17-2011
drkidd22
Ok so now that I can calculate the checksum I'm trying to send it to the end of a string so I can write the data to an EEPROM. The only problem is that when I do it the checksum bytes are inverted for some reason.

Code:

```int main(short argc, char **argv) {   int i;     unsigned char serNum [9] = "DS0008D-";   unsigned char serNum1 [6] = "0111A";   unsigned char ckSum_data [13];   unsigned short checksum[3]={0x00,0x00,0x00};                   for (i = 0; i < 5; i++)                 {                         ckSum_data [i + 8] = serNum1[i];         }                 for (i = 0; i < 8; i++)         {                         ckSum_data [i] = serNum[i];         } //ckSum_data[] should hold the entire serial number (DS0008D-0111A)   checksum[0] = CalcChksum(ckSum_data, 13);                   memcpy(&ckSum_data[14],&checksum[0],3);                 cout << "\n" << checksum[0]; // Checksum output on console is FD 2B }```
So basically the last two bytes (15,16) should contain the checksum FD 2B.

15 >> FD
16 >> 2B

But the freaking thing is putting them reversed.
• 01-17-2011
kona49er
Looks like you're bumping into an endian issue.
Look at Endianness - Wikipedia, the free encyclopedia
• 01-17-2011
drkidd22
That makes sense and I think the memcpy is causing this issues, how can I fix this?
• 01-17-2011
drkidd22
This is what I did. It places the checksum in the place I want the bytes to be.

Code:

```                low = checksum&0x00FF;                        //lower byte of checksum                 high = (checksum>>8)&0x00FF;        //higher byte of checksum                 memcpy(&ckSum_data[14],&high,1);                 memcpy(&ckSum_data[15],&low,1);```
If there is any other way that this could be done please let me know. Thanks
• 01-17-2011
CommonTater
Quote:

Originally Posted by drkidd22
This is what I did. It places the checksum in the place I want the bytes to be.

Code:

```                low = checksum&0x00FF;                        //lower byte of checksum                 high = (checksum>>8)&0x00FF;        //higher byte of checksum                 memcpy(&ckSum_data[14],&high,1);                 memcpy(&ckSum_data[15],&low,1);```
If there is any other way that this could be done please let me know. Thanks

I trust you adjusted the size of your ckSum_data array... if you're still using the original definition from above 14 and 15 are out of bounds and may cause problems known as "undefined behaviour"... i.e. screwups.
• 01-17-2011
kona49er
Quote:

Originally Posted by drkidd22
This is what I did. It places the checksum in the place I want the bytes to be.

Code:

```                low = checksum&0x00FF;                        //lower byte of checksum                 high = (checksum>>8)&0x00FF;        //higher byte of checksum                 memcpy(&ckSum_data[14],&high,1);                 memcpy(&ckSum_data[15],&low,1);```
If there is any other way that this could be done please let me know. Thanks

I would not be swapping the bytes. This assumes you know something about
the system architecture. It would not work if you wrote the data on a system
with one Endian and read it back on a system with the opposite Endian.

Not knowing your requirements it's hard to say how you should proceed.

If you can afford to waste a byte of PROM space then you should pad the
data when count is not a multiple of 2. Then you could stuff the checksum
at the end of the data with *(unsigned short *)&ckSum_date[14] = checksum;
And extract it the same way.

If you can't afford to waste a byte of PROM space then maybe an
8 bit checksum could be used, since your char arrays are small.