我可能对此有误解,但是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)
进行了无效的取消引用。
答案 0 :(得分:1)
从 C99,7.20.3-内存管理功能(重点是我):
如果分配成功,则返回的指针将进行适当对齐,以便可以将其分配给指向任何类型对象的指针,然后将其用于访问此类对象或此类对象的数组分配的空间(直到明确释放空间为止)。
这意味着可以按照char
的数组访问分配的内存(根据您的示例),因此可以很好地定义指针算法。