0

I have been working on a project and I spent the last hour trying to find the bug in my code. After closer inspection, I noticed something rather odd which has been the problem all along.

The addresses of the initial elements of my array are strangely comparing equal with memcmp(). I have separated my code and tried a test code, and I got similar results. Can somebody explain this odd behavior?

#include <stdio.h>
#include <string.h>

int main(void)
{
    char buf[256];

    char *p1 = buf;
    char *p2 = buf + 3;

    if (memcmp(p1, p2, sizeof(char *)) == 0) {
        puts("equal...");
    }

    p1 = buf + 100;
    p2 = p1  + 3; 

    if (memcmp(p1, p2, sizeof(char *)) == 0) {
        puts("equal...");
    }
    return 0;
}
  • 1
    `memcmp(p1, p2, ...` is *not* comparing the addresses of the pointers. It is not comparing their values, either. What it does is comparing the number of bytes equal to `sizeof(char *)` starting at the addresses held by `p1, p2`. Since nothing has been stored there, the result of the comparison is undefined. One of many possible outcomes of *undefined* is that they may happen to compare equal. – dxiv Jul 23 '16 at 07:28

5 Answers5

2

You have undefined behavior.

Local variables, no matter if simple integers or arrays, are not initialized. Their value is indeterminate. Using them in any way, even reading from them, before initialization leads to undefined behavior.

Also, you are not comparing two characters, you are comparing 4 or 8 characters at a time, depending on if you're on a 32 or 64 bit system. If you want to compare single characters you should use sizeof(char) (which is specified to always be equal to 1). Neither are you comparing the pointers, you are comparing what they point to.

If you want to compare two single characters use the compare-equal operator == instead, like e.g. *p1 == *p2 or plainly buf[0] == buf[3].

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • 1
    If you want to compare single characters, you're probably really best off either using array indexing or dereferencing and directly comparing equality, rather than using memcmp in the first place. – Taywee Jul 23 '16 at 07:28
  • 1
    now I see it. I should have written:`memcmp(&p1, &p2, sizeof(char *)) == 0)` right?? –  Jul 23 '16 at 07:32
  • @layzak Absolutely not. Are you trying to compare their contents or the addresses themselves? To compare the contents, you'd want to replace `sizeof(char *)` with the actual buffer sizes. To compare the addresses, it's just `py == p2`. Remember that a pointer can be compared to other pointers trivially. – Taywee Jul 23 '16 at 07:35
  • @layzak Or `p1 == p2`. And *that* is not undefined behavior. And how you initialize `p1` and `p2` will be false no matter the contents of the array. – Some programmer dude Jul 23 '16 at 07:35
  • @JoachimPileborg I actually wanted to compare pointers not what they point to,but I haven't eaten my breakfast yet :) –  Jul 23 '16 at 07:37
  • 1
    @layzak: yes, that's what you want. You're surprised that it looks like `buf` and `buf+3` have the same pointer value. But to compare the memory representations of a variable, like a pointer, you have to pass the memory address of that variable to `memcmp`. – librik Jul 23 '16 at 07:37
1

memcmp does not compare addresses. It compares memory.

int memcmp(const void *s1, const void *s2, size_t n);

memcmp compares the first n bytes of s1 and s2 to see if they're equal.

Here, you have

if (memcmp(p1, p2, sizeof(char *)) == 0) {

sizeof(char *) is going to be your pointer size, likely 4 or 8, depending on your architecture.

This means that you are comparing to see if the first sizeof(char *) bytes of p1 and p2 are equal. As you never initialize this data, it's going to be pretty much random what happens. I'm assuming that your actual code zeros it, which would easily explain why it always compares equal.

Taywee
  • 1,313
  • 11
  • 17
0

Run the code in the debugger and check what the contents of buf are. Some compilers zero out all items in an array in debug mode and give them indetermined values in release build. Or run the code in release build and check if they still are equal

Serve Laurijssen
  • 9,266
  • 5
  • 45
  • 98
0

I think memcmp() compares the content present at memory not the pointers you pass. If you want to compare the pointers (addresses) pass pointers to pointers and size as sizeof(1)

Hence modified code for your question

/* to compare addresses */
/* simple one */
if(p1 == p2)

/* redundant one */
if(!memcmp(&p1, &p2, sizeof(p1))
nebuch
  • 6,475
  • 4
  • 20
  • 39
Madhusoodan P
  • 681
  • 9
  • 20
0

You're trying to compare the 4-byte contents of the pointer variables p1 and p2. But you're actually comparing the 4 bytes that p1 and p2 point to, because that's what memcmp does.

The first two arguments to memcmp are the memory addresses of the data you want to look at, and the memory address of a variable is indicated by using the & operator before the variable.

You want

memcmp(&p1, &p2, sizeof(char*));
librik
  • 3,738
  • 1
  • 19
  • 20
  • `You want memcmp(&p1, &p2, sizeof(char*));` Or simply. and more readable, just `p1 != p2;`. – dxiv Jul 23 '16 at 07:38