Why is there unwanted value when I try to find the difference in structure pointers?

Here is what I tried to do: -

struct Test
{
    int i;
    char s;
    float f;
};  
int main()
{
    int sizestruct=sizeof(struct Test);
    printf("size of struct=%d\n", sizestruct);
    int maxedge;
    printf("enter maxedge value");
    scanf("%d", &maxedge);
    struct Test *sptr1, *sptr2;
    sptr1=(struct Test *) 1000;
    sptr2=(struct Test *) maxedge;
    printf("sptr1=%d, sptr2=%d\n",sptr1, sptr2);
    printf("then sptr2-sptr1=%d\n", sptr2-sptr1);
    return 0;
}  

      

Now the output I get is ok if maxedge = 1996 (output is 83). Even for the values ​​of 1997, 1998 and 1999, its meaning was the same. But for values ​​from 2000 to 2007, a spam value appears. From 2008 to 2011, the output is 84. But from 2012 to 2019, the output is again obtained.

Now consider this structure:

struct Test {
    int i;
    char s;
    float f;
    char s1;
};  

      

For the above structure, regardless of the value for maxedge, the output is correct. I can't figure out why the spam value for the above code is!

+3


source to share


3 answers


I tried my code. It doesn't print garbage, but it does print values ​​that don't seem to match the others at first glance. (83, -1431655682, 1431655849, 84)

I'm not sure why it behaves this way, but in general unexpected behavior can result (as in this case) from undefined behavior.

If the difference between pointers, measured in bytes, is not a multiple of 12 (the size of one structure), as we can see, rather strange things can happen.

The division by 12 obviously happens in such a way that it divides by 4 and then by 3, and the latter is done in such a way that it happens.

Let's look at the generated assembler output:

    movl    28(%esp), %edx
    movl    36(%esp), %eax
    subl    %eax, %edx
    movl    %edx, %eax

      



It was a subtraction.

    sarl    $2, %eax
    imull   $-1431655765, %eax, %eax
    movl    %eax, 4(%esp)

      

Here, we first divide by 4 and then do the multiplication with the value -1431655765 which is the signed misrepresentation of the unsigned value 2863311531.

If I multiply this value by a number that divides by 3 and only consider the lower 32 bits, I get the number divided by 3. This does not work with other numbers, but is probably faster than division.

So, we see that if some conditions are not met, for example, the divisibility of the number 4 4 by 3, strange things happen. But that's okay, since not meeting these conditions is undefined behavior.

+6


source


The pointer difference might surprise you in C. It will assume that you are asking for an index in an array, for example. since it is the array[index]

same as *(array+index)

, naturally, this is rotated when p=&(array[index])

then p - array == index

.

Does your result remain garbage?



Well maybe then you can think, and not less offsets sizeof(struct Test)

, you are somewhere between index == i and index == i + 1. I doubt this behavior is specified anywhere, so you can expect nothing ...

+3


source


The undefined behavior subtracts two pointers that are not both pointing to elements of the same array (or one to one end of that array).

Usually the compiler assumes that your code follows a standard and therefore generates code similar to subtracting addresses and dividing by object size. Works well if your code compiles, can cause garbage if your code doesn't work.

+1


source







All Articles