-1

Given a packed struct like this:

struct RSDPDescriptor {
    char Signature[8];
    uint8_t Checksum;
    char OEMID[6];
    uint8_t Revision;
    uint32_t RsdtAddress;
} __attribute__ ((packed));

How can I sum all of the individual bytes in it?

Barry
  • 286,269
  • 29
  • 621
  • 977
Makerimages
  • 384
  • 6
  • 27

2 Answers2

6

I would just forward to std::accumulate:

template <typename T>
size_t sum_bytes(const T& obj) {
    const unsigned char* p = reinterpret_cast<const unsigned char*>(&obj);
    return std::accumulate(p, p + sizeof(T), 0u);
}
Barry
  • 286,269
  • 29
  • 621
  • 977
  • Kernel programming - can't use std:: stuff. – Makerimages May 13 '15 at 20:16
  • 3
    @Makerimages Things like what you actually want to do and restrictions you have belong in the question. – Barry May 13 '15 at 20:16
  • @Makerimages `std::accumulate` is usually a header-only implementation. (aka the code ends up as part of your object file. It doesn't come from a standard precompiled library.) So you sould be fine. (But I would double check your particular compiler first.) – programmerjake May 13 '15 at 20:20
5

Here is some code that shows two ways to do it.

The first way is easier and more efficient, but will give the wrong result for a struct that doesn't have the packed attribute (since it will incorrectly include the padding bytes in its tally).

The second approach will work on any struct, padded or packed.

#include <stdio.h>
#include <stdlib.h>

template<typename T> int CountBytes(const T & t)
{
   int count = 0;
   const unsigned char * p = reinterpret_cast<const unsigned char *>(&t);
   for (int i=0; i<sizeof(t); i++) count += p[i];
   return count;
}

struct RSDPDescriptor {
    char Signature[8];
    unsigned char Checksum;
    char OEMID[6];
    unsigned char Revision;
    unsigned int RsdtAddress;
} __attribute__ ((packed));

int main(int, char **)
{
   struct RSDPDescriptor x;

   int byteCountFast = CountBytes(x);
   printf("Fast result (only works correctly if the struct is packed) is:  %i\n", byteCountFast);

   int byteCountSafe = CountBytes(x.Signature) + CountBytes(x.Checksum) + CountBytes(x.OEMID) + CountBytes(x.Revision) + CountBytes(x.RsdtAddress);
   printf("Safe result (will work even if there is padding) is:  %i\n", byteCountSafe);

   return 0;
}
Jeremy Friesner
  • 70,199
  • 15
  • 131
  • 234