2

I've written the following C code to compare two areas of memory and check if they are identical

#include <stdio.h>

struct s1 {

   int a, b;
   char c;

} s1;


int memcmpwannabe(void* value1, void *value2, int size1, int size2) {

   if(size1 != size2)
      return -1;

   if(size1 == 0 || size2 == 0)
      return -1;

   //memcmp() wannabe
   char *p1 = value1;
   char *p2 = value2;
   int sz = size1;

   do {
       if(*p1 != *p2)
           break;
       else
           p1++, p2++;
   }
   while(--sz != 0);

   if(sz == 0)
      return 0;

   return -1;

}


int main() {

   struct s1 v1;
   struct s1 v2;

   v1.a = 1;
   v1.b = 2;
   v1.c = 'a';

   v2.a = 1;
   v2.b = 2;
   v2.c = 'a';

   int res = memcmpwannabe((void*) &v1, (void*) &v2, sizeof(s1), sizeof(s1));

   printf("Res: %d\n", res);

}

The structures are identical, but it will return -1 anyway. After some debugging i found that the 3 padding bytes after the char variable are filled with random data, not with zeroes as i was expecting.

Knowing this and the fact that i want to keep it as generic as possible (so using void* as arguments), can somebody point me to an alternative byte to byte comparison?

(Before somebody asks, i'm writing a custom memcmp() because in some implementations it will continue after a difference

debevv
  • 145
  • 2
  • 8
  • 2
    There will be padding after the c structure member. Containing (more or less) random values. These can compare unequal to other random bytes. – joop Mar 05 '15 at 15:20
  • 1
    Can you modify the structure members to *include* the padding? Then you can set them to a known value -- i.e., 0 or any other constant. – Jongware Mar 05 '15 at 15:27
  • Why do you consider two 0-length-ranges different? – Deduplicator Mar 05 '15 at 15:29
  • @Deduplicator Sorry, that is something related to the program i'm writing, just ignore it. – debevv Mar 05 '15 at 15:32
  • Does `memset(&s1, 0, sizeof(s1));` after the declaration of both variables helps? – David Ranieri Mar 05 '15 at 15:32
  • @AlterMann: Even if it would, that's at best a band-aid which is not really reliable. – Deduplicator Mar 05 '15 at 15:34
  • setting the whole struct to a known value, immediately after declaration of any instance would work for making comparisons. Otherwise, the comparison would need to be field by field. Then the comparison would only work for the specific struct definition. Then, memcmp() would work and the posted code would not be needed – user3629249 Mar 05 '15 at 16:32
  • Note: Functional differences between `memcmpwannabe()` and `memcmp()`. 1) `size`: `int` v. `size_t`, 2) when `size == 0`, returns -1 v. 0 for `memcmp()` 3) On difference: `memcmpwannabe()` only returns -1, `memcmp()` returns + or - values to indicate _order_. 4) `memcmpwannabe()` is UB if `size < 0`, not applicable to `memcmp()` – chux - Reinstate Monica Mar 05 '15 at 16:39
  • @chux 1) yes, i think it would be better with size_t 2/3) design choice, it hasn't to emulate the original memcmp() 4) you got a point – debevv Mar 05 '15 at 17:18
  • @user3629249 do you mean doing a memset() like Alter Mann wrote? – debevv Mar 05 '15 at 17:23
  • Some thoughts: If `memcmpwannabe()` does not have to emulate the original `memcmp()` then "writing a custom memcmp() because in some implementations it will continue after a difference" does not apply - after all, this is then a _different_ function. So either the function is like `memcmp()` aside from the "continue after a difference" issue and should mimic `memcpy()` functionality as able, or it isn't. If the latter case, recommend that it receive a more distinctive name. – chux - Reinstate Monica Mar 05 '15 at 18:08

1 Answers1

3

Knowing this and the fact that i want to keep it as generic as possible (so using void* as arguments)

If you only take void * pointers, by definition you know nothing about the internal organization of the objects. Which means you know nothing about the meaning of the bytes (which are in "real" members and which are in hidden, padding-only members).

I would say this is not something that you can easily do with standard C.

cnicutar
  • 178,505
  • 25
  • 365
  • 392
  • @pattern23 I don't know. C++ may have some fancy way to get the type of the pointed-to object (I don't think RTTI covers that?) but I am only speculating. – cnicutar Mar 05 '15 at 15:43
  • Let's say i find a fancy way to discover the pointed type. Then, how can i write a generic function that iterates through the members and compare them one by one? – debevv Mar 05 '15 at 17:27
  • @pattern23 In that case you probably need more magic: something like annotations left over by the compiler for debuggers' use. – cnicutar Mar 05 '15 at 17:42