Is this use of the Effective Type rule strictly co

2019-05-24 12:59发布

The Effective Type rule in C99 and C11 provides that storage with no declared type may be written with any type and, that storing a value of a non-character type will set the Effective Type of the storage accordingly.

Setting aside the fact that INT_MAX might be less than 123456789, would the following code's use of the Effective Type rule be strictly conforming?

#include <stdlib.h>
#include <stdio.h>

/* Performs some calculations using using int, then float,
  then int.

    If both results are desired, do_test(intbuff, floatbuff, 1);
    For int only, do_test(intbuff, intbuff, 1);
    For float only, do_test(floatbuff, float_buff, 0);

  The latter two usages require storage with no declared type.    
*/

void do_test(void *p1, void *p2, int leave_as_int)
{
  *(int*)p1 = 1234000000;

  float f = *(int*)p1;
  *(float*)p2 = f*2-1234000000.0f;

  if (leave_as_int)
  {
    int i = *(float*)p2;
    *(int*)p1 = i+567890;
  }
}

void (*volatile test)(void *p1, void *p2, int leave_as_int) = do_test;

int main(void)
{
  int iresult;
  float fresult;
  void *p = malloc(sizeof(int) + sizeof(float));
  if (p)
  {
    test(p,p,1);
    iresult = *(int*)p;
    test(p,p,0);
    fresult = *(float*)p;
    free(p);
    printf("%10d %15.2f\n", iresult,fresult);
  }
  return 0;
}

From my reading of the Standard, all three usages of the function described in the comment should be strictly conforming (except for the integer-range issue). The code should thus output 1234567890 1234000000.00. GCC 7.2, however, outputs 1234056789 1157904.00. I think that when leave_as_int is 0, it's storing 123400000 to *p1 after it stores 123400000.0f to *p2, but I see nothing in the Standard that would authorize such behavior. Am I missing anything, or is gcc non-conforming?

2条回答
我想做一个坏孩纸
2楼-- · 2019-05-24 13:40

The generated machine code unconditionally writes to both pointers:

do_test:
        cmpl    $1, %edx
        movl    $0x4e931ab1, (%rsi)
        sbbl    %eax, %eax
        andl    $-567890, %eax
        addl    $1234567890, %eax
        movl    %eax, (%rdi)
        ret

This is a GCC bug because all stores are expected to change the dynamic type of the memory accessed. I do not think this behavior is mandated by the standard; it is a GCC extension.

Can you file a GCC bug?

查看更多
3楼-- · 2019-05-24 13:44

Yes, this is a gcc bug. I've filed it (with a simplified testcase) as https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82697 .

查看更多
登录 后发表回答