Home > database >  Does comparing two pointers do more than to just check their adresses?
Does comparing two pointers do more than to just check their adresses?

Time:10-26

I'm rewriting part of libc, more specifically memmove as an exercise and after being unable to do it myself I looked for its source code and found this (and variations of it):

void    *memmove(void *dest, const void *src, size_t n)
{
  char *d = dest;
  const char *s = src;
  if (d < s)
    while (n--)
      *d   = *s  ;
  else
    {
      char *lasts = s   (n-1);
      char *lastd = d   (n-1);
      while (n--)
        *lastd-- = *lasts--;
    }
  return (dest);
}

My question concerns the 5th line if (d < s) for me this would only make sense if d and s contained the size of both dest and src which as far as my understanding goes is not true. So is this comparison doing anything besides checking the position of the addresses or is my understanding of pointers completely flawed?

Is there any purpose to this code? Sorry in advance if I am completly wrong pointers can be very confusing.

CodePudding user response:

is this comparison doing anything besides checking the position of the addresses?

No. It checks if d has a lower address than s. If it does, it selects the first strategy, to copy from the beginning of the memory area and forward - otherwise it copies from the end of the memory area backwards

This is to not mess up the result in case [d,d n) and [s,s n) are overlapping.

Example:

      --- --- --- 
src  | x | y | z |
      --- --- --- --- 
dest     |   |   |   |
          --- --- --- 
     ^               ^
     |               |
low mem addr    high mem addr

Here the second strategy must be chosen. Consider what would happen if the the first strategy is chosen instead:

dest[0] = src[0]; // which is x
dest[1] = src[1]; // which is ... x, because the above op overwrote the y

CodePudding user response:

The function memmove assumes that the source and destination arrays are overlapped. That is that they are pointers that point to different parts of the same array. So for example this if statements

if (d < s)

checks whether the element pointed to by the pointer d precedes the element pointed to by the pointer s in the array.

Consider an example. Let's assume that there is declared an array

char s[] = "Hello World!";

that is the array contains the string "Hello World!". And you want to change the array such a way that it will contain the string "World!". What you need is to move the part of the source string that contains the substring "World!" to the beginning of the array.

If you will write

strcpy( s, s   6 );

then such a call invokes undefined behavior because the function strcpy does not allow to use overlapped subarrays.

Using memmove you may write

memmove( s, s   6, 7 );

In this case relative to the provided by you function definition the pointer d has the value of the original array s and the pointer s has the value equal to the expression s 6.

As the value of d is less than the value of the pointer s then this part of the function gets the control

if (d < s)
  while (n--)
    *d   = *s  ;

Pay attention to that according to the C Standard (6.5.8 Relational operators)

5 When two pointers are compared, the result depends on the relative locations in the address space of the objects pointed to. If two pointers to object types both point to the same object, or both point one past the last element of the same array object, they compare equal. If the objects pointed to are members of the same aggregate object, pointers to structure members declared later compare greater than pointers to members declared earlier in the structure, and pointers to array elements with larger subscript values compare greater than pointers to elements of the same array with lower subscript values. All pointers to members of the same union object compare equal. If the expression P points to an element of an array object and the expression Q points to the last element of the same array object, the pointer expression Q 1 compares greater than P. In all other cases, the behavior is undefined.

That is from the quote it follows that the two pointers passed to the function memmove shall point to elements of the same array to guarantee the defined behavior for the comparison of the pointers in this if statement

if (d < s)

Otherwise the behavior is undefined.

  • Related