LinuxQuestions.org
Latest LQ Deal: Linux Power User Bundle
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 01-08-2005, 01:19 PM   #1
george_mercury
LQ Newbie
 
Registered: Jun 2004
Location: Slovenia
Distribution: Gentoo
Posts: 27

Rep: Reputation: 15
Calculating checksum of a structure


Hi! I need to know, how to calculate the checksum of this structure:
Code:
struct stepdata {
	uint8_t cmd;
	uint8_t acca;
	uint8_t accb;
	uint16_t indx;
	uint16_t indy;
	uint16_t stack;
	uint8_t status;
	uint32_t oppcode;
	uint8_t checksum;
};
I've tried to make a pointer in order to read the data of the structure byte-by-byte, but no matter what I do I get "incompatible pointer type". So what should I do?

George
 
Old 01-08-2005, 08:55 PM   #2
Inunu
LQ Newbie
 
Registered: Jan 2005
Location: NZ
Distribution: Customized MDK 9
Posts: 13

Rep: Reputation: 0
Hi George.

You can explicitly cast one pointer to another of different type by doing something like this and use the new pointer to process whatever that is in there.
char *ptr=(char *)&data;

Unfortunately in your example it will run into some problem because the stepdata structure is not well-aligned. GCC will pad bytes to make 32bit int's and struct boundary aligned to 32bit unless you ask it not to do so with __attribute__((packed)).

See http://www.delorie.com/djgpp/v2faq/faq22_11.html for more details about sizeof struct and extra paddings.

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

struct stepdata {
	uint8_t cmd;
	uint8_t acca;
	uint8_t accb;
	uint16_t indx;
	uint16_t indy;
	uint16_t stack;
	uint8_t status;
	uint32_t oppcode;
	uint8_t checksum;
} __attribute__((packed)); /* NOT TO PAD, otherwise sizeof(struct stepdata)=20 instead of 15 */

unsigned char checksum(char *data, int sz){
  int i;
  unsigned char checksum;
  for(i=0, checksum=0; i<sz; i++)
    checksum+=data[i];
  return checksum;
}

void dump(unsigned char *data, int sz){
  int i;
  
  printf("Dump data (%d):", sz);
  for(i=0; i<sz; i++){
    if((i&7)==0) printf("\n");
    printf("%02X ", data[i]);
  }
  printf("\n");
}  

main(){
  struct stepdata data={1,2,3,4,5,6,7,8,0};
  unsigned char *ptr=(unsigned char *)&data;
  int sz=sizeof(struct stepdata);
  
  dump(ptr, sz);
  data.checksum=checksum(ptr, sz);
  printf("\nCalculated checksum: %2X\n", data.checksum);
  dump(ptr, sz);
}
Here is the result.

linux~$ ./checksum
Dump data (15):
01 02 03 04 00 05 00 06
00 07 08 00 00 00 00

Calculated checksum: 24
Dump data (15):
01 02 03 04 00 05 00 06
00 07 08 00 00 00 24

Last edited by Inunu; 01-08-2005 at 08:56 PM.
 
Old 01-08-2005, 10:15 PM   #3
randyding
Member
 
Registered: May 2004
Posts: 552

Rep: Reputation: 31
One more bit of info about your packing problem, if you choose to force byte packing of that structure you will get a "Bus Fault" if you compile and run your software on any processor other than Intel X86 because the 16 and 32 bit integers will not be word aligned. For example, it will crash on a Sparc.
i.e... struct stepdata data={1,2,3,4,5,6,7,8,0}; **bus fault**
But it will work on Intel.
 
Old 01-09-2005, 05:07 AM   #4
Inunu
LQ Newbie
 
Registered: Jan 2005
Location: NZ
Distribution: Customized MDK 9
Posts: 13

Rep: Reputation: 0
In x86 it can get away from crashes, but with performance penalty. To avoid this you should

1) manually pad extra bytes so that int16 words and int32 dwords are 16bit and 32bit aligned respectively, or
2) define dedicated function to perform the checksum over this particular structure type

The following one is an attempt to

A) align int16 and int32 variables., and
B) keep struct size multiple of 32bit.

(If you don't do B, once you have an array of this struct, the 2nd one may have everything mis-aligned.)

Code:
struct stepdata {
	uint8_t cmd; /* 00 */
	uint8_t acca; /* 01 */
	uint8_t accb; /* 02 */
	uint8_t pad1; /* 03 */

	uint16_t indx; /* 04 */
	uint16_t indy; /* 06 */

	uint16_t stack; /* 08 */
	uint8_t status; /* 0A */
	uint8_t pad2; /* 0B */

	uint32_t oppcode; /* 0C */

	uint8_t checksum; /* 10 */
	uint8_t pad3[3]; /*11 */
};
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Calculating email bandwidth with postfix / dovecot benr77 Linux - General 0 08-01-2005 06:13 PM
calculating download time/speed juanb Linux - Networking 4 03-19-2004 02:49 PM
need perl help calculating fibonacci numbers WorldBuilder Programming 5 12-17-2003 01:41 AM
Calculating Surface Distance! john23 Programming 1 11-27-2003 01:45 PM
calculating server load hardigunawan Programming 5 06-27-2003 11:07 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 12:14 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration