Sumowanie bajtów struktury

0

Cześć.

Wzorując się jakimś znalezionym w sieci kodem, napisałem sobie funkcję, która będzie mi sumowała bajty zapisanej w pamięci struktury.
Docelowo kod ten ma być pomocny w policzeniu sumy kontrolnej.
Spotkałem się jednak ze stwierdzeniem, że nie powinno się rzutować na unsigned short * jeżeli w pamięci nie są faktycznie przechowywane dane typu short, natomiast powinno się rzutować na typ char *.
Dlaczego?
Które stwierdzenie jest poprawne i które powinno się stosować?

#include <stdio.h>
#include <string.h>
 
struct pseudo_header
{
    int var1;
    int var2;
    char name[25];
};
 
void csum(const unsigned short* ptr, int nbytes)
{
 
    unsigned long sum = 0;
 
    for(int i = 0; i < sizeof(struct pseudo_header); i++)
    {
        sum+= ptr[i];
    }
 
    printf("%lu", sum);
}
 
int main() {
 
    struct pseudo_header psh;
    char datagram[4096];
 
    psh.var1 = 10;
    psh.var2 = 20;
 
    strcpy(psh.name, "test");
    memcpy(datagram, &psh, sizeof(struct pseudo_header));
 
    csum((unsigned  short*)datagram, sizeof(struct pseudo_header));
 
    return 0;
}
0

Chodzi o tzw. alignment, czyli wyrównanie. Jak rzutujesz na char *, to każde takie rzutowanie jest bezpieczne, bo rzutujesz na dane, które są z automatu wyrównane do 1 bajta. W przypadku unsigned short potrzebowałbyś dodatkowych gwarancji, aby takie rzutowanie zadziałało.

0

Poza tym w przypadku twojego kodu nie ma problemu, żeby datagram był typu unsigned short[2048], a wtedy reszta kodu powinna działać po prostu działać.

0

Hmm, poprzednia wersja kodu była ok, tzn. z przyjmowaniem ilości słów, które będą brane pod uwagę przy liczeniu sumy. Poza tym - weź pod uwagę, że sizeof zwraca Ci rozmiar struktury jako wielokrotność rozmiaru char, a Ty bierzesz za każdym razem ilość danych równych rozmiarowi unsigned short. W warunku pętli przy zwiększaniu licznika powinieneś napisać raczej:

i += sizeof(*ptr)
0

Wygląda na to że w tutorialach rzutowanie na dwubajtowe unsigned short jest zamierzone bo tak obliczają sumę kontrolną:

// Function for checksum calculation. From the RFC,
// the checksum algorithm is:
//  "The checksum field is the 16 bit one's complement of the one's
//  complement sum of all 16 bit words in the header.  For purposes of
//  computing the checksum, the value of the checksum field is zero."
unsigned short csum(unsigned short *buf, int nwords)
{
        unsigned long sum;
        for(sum=0; nwords>0; nwords--) sum += *buf++;
        sum = (sum >> 16) + (sum &0xffff);
        sum += (sum >> 16);
        return (unsigned short)(~sum);
}

czyli sumują wartość liczbową jaka jest zapisana w kolejnych dwóch bajtach, a nie kolejnym bajcie, ale czemu? Może sumy są tak duże że jeden bajt ich nie przechowa? (policz sobie jaką maksymalną wartość może przechować jeden bajt bez znaku, jak się nie rypłem to mi wychodzi 255).

1 użytkowników online, w tym zalogowanych: 0, gości: 1