将一种类型的指针转​​换为另一种类型的指针的局限性

时间:2019-02-18 11:57:34

标签: c pointers language-lawyer

在理解“指针到”类型的转换时遇到了一些麻烦。让我提供一些示例:

struct test{
    int x;
    int y;
};

1。

void *ptr = malloc(sizeof(int));
struct test *test_ptr = ptr;   //OK 7.22.3(p1)
int x = test_ptr -> x;         //UB 6.2.6.1(p4)

2。

void *ptr = malloc(sizeof(struct test) + 1);
struct test *test_ptr = ptr + 1; //UB 6.3.2.3(p7)

3。

void *ptr = malloc(sizeof(struct test) + 1);
struct test *test_ptr = ptr; //OK 7.22.3(p1)
int x = test_ptr -> x; //Unspecified behavior or also UB?

我对案件的理解是

  1. malloc返回的指针转换本身可以确定为7.22.3(p1):
  

如果分配成功,则返回的指针已适当对齐,因此   可以将其分配给指向任何类型对象的指针   基本对齐要求

访问不正确,因为test_ptr不能指向有效的struct test_ptr对象,因为它的大小小于分配给malloc的对象的大小,导致UB,如6.2.6.1(p4)所述)。

  1. 这是UB,因为我们无法说出ptr + 1指针的对齐方式。 6.3.2.3(p7)对此进行了解释:
  

指向对象类型的指针可能会转换为指向对象类型的指针   不同的对象类型。如果结果指针不正确   对于引用类型,该行为是不确定的。

标准3中的情况如何解释?

在标准中没有指定(至少我找不到)是否可以将没有声明类型的对象的指针转换为大小小于一个已分配对象的对象的指针? (我这里不考虑像malloc(10 * sizeof(struct test));这样的数组分配,这在7.22.3(p1)中有明确说明)。 6.2.6.1(p4)状态:

  

存储在任何其他对象类型的非位字段对象中的值   由n×CHAR_BIT位组成,其中n是该对象的大小   类型,以字节为单位。

分配的对象不是由sizeof(struct test) x CHAR_BIT位组成,而是(sizeof(struct test) + 1) x CHAR_BIT

1 个答案:

答案 0 :(得分:1)

这必须是合法的,因为在C中,我们有flexible array members

typedef struct flex_s {
  int x;
  int arr[];
} flex_t;
void *ptr = malloc(sizeof(flex_t) + sizeof(int));
flex_t *flex = ptr;
flex->arr[0]; // legal

因此,如果您想从标准中得到答案,请查看其对灵活数组成员的定义及其分配,然后给出规则。

您可以先看看the free draft of C11第114页的示例20。