Question

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.

Was it helpful?

Solution

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;
    }
}

OTHER TIPS

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

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 ==.

Look, I'm a math geek, I know, but the underlying issue sounds like "gee, what is the natural ordering of these things?"

Is the underlying data raw bits, like a Bignum? Then cast them to unsigned char and compare them in a loop. A little thought of the order in which you compare will make it most efficient. An interesting point is when length of A ≠ length of B: is A≠B then by definition, or is it the numerical value you're comparing, in which case leading bytes of 0x00 aren't significant?

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.

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?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top