• Some users have recently had their accounts hijacked. It seems that the now defunct EVGA forums might have compromised your password there and seems many are using the same PW here. We would suggest you UPDATE YOUR PASSWORD and TURN ON 2FA for your account here to further secure it. None of the compromised accounts had 2FA turned on.
    Once you have enabled 2FA, your account will be updated soon to show a badge, letting other members know that you use 2FA to protect your account. This should be beneficial for everyone that uses FSFT.

C question - writing into a byte array

NeuroMaster

Limp Gawd
Joined
Jun 12, 2002
Messages
346
I'm working with a byte array and I'm having a devil of a time figuring out how to write in data that's more than one char (byte) long. It looks something like this:

Code:
#define RDT_PKTSIZE 64
struct packet {
    char data[RDT_PKTSIZE];
};

packet pkt;

I'd like to use the first two bytes for a vanilla 16-bit internet checksum, so say we set those to zero and then copy in the payload.
Code:
memset(pkt.data, 0, 2);
memcpy(pkt.data + 2, buffer, 62);

So far so good. Now say we've got a checksum function that'll return the 16-bit internet checksum of bytes bytes of data starting at addr prototyped like this:
Code:
short checksum(char *addr, int bytes)

I've more or less gotten this much working. I'm a bit uncomfortable with some of the example implementations I've found of the internet checksum because most of the stuff out there is tailored toward making things blazing fast, not beginner coders. I'm hoping that a few issues (like dealing with unsigned vs signed types) aren't the big problem.

The big problem is that once I've returned this short, I have no idea how to write it into the first two bytes. I've tried just writing it into pkt.data[0] and hoping it'd overflow/whatever you call it into the next byte nicely, I've tried bit-masking/bit-shifting the short I get out of the checksum into data[0] and data[1]... I've basically banged my head against the problem for a few hours now and I can't seem to get it to work. No matter what I try, I can't put the information I want into the byte array, then pull it back out into a short.

I shouldn't even have to - running the internet checksum algorithm on the whole array after inserting the checksum into that field should return zero, but I keep getting a nonzero result. This seems like a pretty trivial problem, but there's just something I'm missing - maybe a command or system call I've just forgotten or never learned. I can't imagine this is supposed to be so difficult.

Any thoughts? I've tried to describe my situation as best I can, but I'm a little flustered - let me know ifyou need something clarified.

Thanks.
 
I didn't test any of this, but my understanding of your problem is that you want to do something like this:

Code:
  // Compute 'internet checksum'
  short checksum(char* addr, int bytes)
  {
     // We should add 16 bit numbers
     short* pShorts = (short*)addr;
     int	  iShorts = bytes/2; // Fortunately, we know this to be an even number
     int	  iSum   = 0;
     for(int i = 0; i < iShorts; i++)
     {
  	  iSum += iShorts[i]; // Add everything upp
     }
     // Get the lower 16 bits
     short iChecksum = iSum & 0xFFFF;
     // Add the carry to the result
     iChecksum += iSum >> 16;
     return iChecksum;
  }
  ...
     #define RDT_PKTSIZE 64
     struct packet
     {
  	  char data[RDT_PKTSIZE];
     } pkt;
      // We don't need to do this, we're going to set these in just a few lines anyway
     memset(pkt.data, 0, 2);
     memcpy(pkt.data+2, buffer, 62);
     // Get the checksum
     short chksum = checksum(&pkt[2], 62); 
     // Get the high byte
    pkt.data[0] = chksum >> 8; // Shift down the high 8 bits
    // Get the low byte
    pkt.data[1] = chksum & 0xFF; // Get the low 8 bits
 // Or replace the above two lines with
 memcpy(&pkt.data[0], &chksum, sizeof(short));
  ...
Post your code if you have problems

Edit: oops, I posted C++ code, but the conversion to C should be trivial
 
NeuroMaster said:
I'm working with a byte array and I'm having a devil of a time figuring out how to write in data that's more than one char (byte) long.


i know that many would discourage their use, and with good reason for bad programmers, but you could use a union.

Code:
#include<iostream.h>
#include<fstream>


union test11{
   char cow[16];
   short int horse;
};

int main(void){

   test11 test;
   for(int i=0; i<16; i++)
      test.cow[i]=1;

   test.horse=147;

   cout<<test.horse<<" ";

   for(int i=2; i<15;i++)
      cout<<(int)test.cow[i]<<" ";


return 0;
}

the output from the above is

147 1 1 1 1 1 1 1 1 1 1 1 1 1

edit: it may be noted that there are constructs in the language for the safe use of unions. i can't really tell you what they are because i do not know, but the above can be done safely. i believe wikipedian ca tell you.

edit: it came back to me. TAGGED unions are pretty safe, untagged (what i have shown) are only as safe as your program logic. i also did the wikipedia on tagged unions

http://en.wikipedia.org/wiki/Tagged_union
 
If the first two bytes are alaways ints, why are you delcaring them as bytes?

Code:
#define RDT_PKTSIZE 64
#pragma pack(push, 1)
struct packet {
    short nChecksum;
    char data[RDT_PKTSIZE - sizeof(short)];
};
#pragma pack(pop)

If you can't do that, than unions are a viable alternative; I'm not so sure why they're to be avoided. I mean, if you need them, you need them.

You can solve this lots of different ways. You can cast:

Code:
*((short*)&(pkt.data[0])) = checksum(/* some prams */);

but this can result in code that ain't portable. If you assume little-endian, the bit banging way is here:

Code:
short nTemp = checksum(/* some params */);
pkt.data[0] = (short) (nTemp & 0xFF);
pkt.data[1] = (short) (nTemp >> 8);
 
Back
Top