views:

392

answers:

6

I have created a dynamic typing system in C in order to create a dictionary that can contain values of different bit widths. The structure of the dynamic object is:

typedef struct
{
    void* Pointer;
    unsigned char Size;   
} Dynamic;

I need to compare two of these Dynamics that hold A2D readings and then compare the difference against a delta value to determine if a change has occurred. One solution I have been able to come up with is to cast them to char arrays and compare them byte by byte, but that doesn't smell right. I also have an idea to make an array of function pointers based on the number of bytes (or perhaps the type) the Dynamics take up and just make a comparison function for each type supported. Can anyone suggest a different approach? It feels like I am missing something.

UPDATE:

Thanks for telling me about memcmp, but I still have the problem of how do I get the delta of the two values? From what I can tell, memcmp just returns an indicator of which value is bigger, not the difference between them.

UPDATE TO UPDATE:

Its turns out that memcmp is useless to me because the architecture I am compiling against is little endian.

If I were going to do a bignum implementation myself then ephemient feels like the right way to go, but I have decided I am just going to memcpy the values into the largest possible type (i.e. unsigned long long) that I will have to deal with and just work the math using those. I can't think of any reason why this would not work, but I recognize that I could be very wrong as C / direct memory manipulation is not my forte.

A: 
Charlie Martin
A: 

If you need just compare for equality - use memcmp(). If you need to count how many bits (or bytes) differ - implement a function similar to memcmp() that runs through both char arrays, compare and count the non-matching patterns.

sharptooth
+2  A: 

Is something like this sufficient?

#include <string.h>
int compare(Dynamic *a, Dynamic *b) {
    if (a->Size != b->Size) return a->Size - b->Size;
    return memcmp(a->Pointer, b->Pointer, a->Size);
}

Creating a bunch of specialized functions if they perform very similar operations seems like overkill.

Addendum

If you want to calculate differences...

int diff(Dynamic *a, Dynamic *b, Dynamic *d) {
    int i, borrow = 0;
    signed char *ap = a->Pointer, *bp = b->Pointer, *dp = d->Pointer;

    assert(a->Size == b->Size && b->Size == d->Size);

    for (i = 0; i < a->Size; ap++, bp++, dp++, i++) {
        // symmetric difference
        *dp = *ap ^ *bp;

        // arithmetic difference, assuming little-endian
        *dp = borrow += *bp - *ap;
        borrow >>= 8;
    }
}
ephemient
+1  A: 

Maybe I'm missing something too...but why don't you use memcmp ?

LB
A: 

I presume that the variable bit sizes are due to some values being larger than others. If you can guarantee that the number of bits always means that bit number is set, then you can first compare the sizes and if the sizes are equal, then do the unsigned byte comparisons. For example "01" only needs 1 bit to store, so its size would be 1, and "100101" requires 6 bits to store so its size is 6. If size(a) > size(b), then (a) > (b).

Are these stored in big or little endian?

Rick C. Petty
+1  A: 

If you're trying to implement bignum functionality (and you might consider someone else's (first google hit on "bignum in C")), you almost assuredly want to calculate the difference through subtraction. Most CPUs implement compare by doing just this and then using the sign of the result or zeroness for <, >, or ==.

plinth