动态分配的内存上的指针算法具有未定义的行为

时间:2019-01-31 14:07:42

标签: c language-lawyer c99 pointer-arithmetic

我可能对此有误解,但是c99规范会阻止动态分配内存上的任何形式的指针算术吗?

从6.5.6p7 ...

  

出于这些运算符的目的,指向不是数组元素的对象的指针的行为与指向长度为1且对象类型为其元素类型的数组的第一个元素的指针相同。

...指向不在数组中的对象的指针将被视为指向1项数组(使用运算符+和-时)。然后在此代码段中:

char *make_array (void) {
    char *p = malloc(2*sizeof(*p));
    p[0] = 1; // valid
    p[1] = 2; // invalid ?
    return p;
}

...第二个下标p[1]无效?由于p指向的对象不在数组中,因此将其视为指向由一项组成的对象,然后指向6.5.6p8 ...

  

将具有整数类型的表达式添加到指针或从指针中减去时,结果将具有指针操作数的类型。如果指针操作数指向数组对象的元素,并且数组足够大,则结果指向与原始元素偏移的元素,以使结果数组元素和原始数组元素的下标之差等于整数表达式。换句话说,如果表达式P指向数组对象的第i个元素,则表达式(P)+ N(相当于N +(P))和(P)-N(其中N的值为n)表示到数组对象的第i + n个元素和第i-n个元素(如果存在)。此外,如果表达式P指向数组对象的最后一个元素,则表达式(P)+1指向数组对象的最后一个元素之后,如果表达式Q指向数组对象的最后一个元素之后,表达式(Q)-1指向数组对象的最后一个元素。如果指针操作数和结果都指向同一数组对象的元素,或者指向数组对象的最后一个元素,则求值不会产生溢出;否则,行为是不确定的。如果结果指向数组对象的最后一个元素之后,则不应将其用作被评估的一元*运算符的操作数。

...由于取消引用超出了数组边界(隐含长度为1),因此我们具有不确定的行为。

编辑:

好的,要尝试弄清让我感到困惑的地方,让我们逐步进行:

1。)p[1]的定义是指*(p+1)
2.)p指向不在数组内部的对象,因此为了评估p+1,将其视为指向长度为1的数组内部的对象。 /> 3.)p+1产生一个指针1,该指针越过p所隐含指向的数组。
4.)*(p+1)进行了无效的取消引用。

1 个答案:

答案 0 :(得分:1)

C99,7.20.3-内存管理功能(重点是我):

  

如果分配成功,则返回的指针将进行适当对齐,以便可以将其分配给指向任何类型对象的指针,然后将其用于访问此类对象或此类对象的数组分配的空间(直到明确释放空间为止)。

这意味着可以按照char的数组访问分配的内存(根据您的示例),因此可以很好地定义指针算法。