我最近注意到,在C中,对于以下声明,array
和&array
之间存在重要区别:
char array[] = {4, 8, 15, 16, 23, 42};
前者是指向char的指针,而后者是指向6个char的数组的指针。同样值得注意的是,书写
a[b]
是*(a + b)
的语法糖。确实,您可以编写2[array]
,并且根据标准它可以完美地工作。因此,我们可以利用这些信息来编写以下代码:
char last_element = (&array)[1][-1];
&array
的大小为6个字符,因此(&array)[1])
是指向数组之后的chars的指针。因此,通过查看[-1]
,我正在访问最后一个元素。这样,我可以交换整个数组:
void swap(char *a, char *b) { *a ^= *b; *b ^= *a; *a ^= *b; }
int main() {
char u[] = {1,2,3,4,5,6,7,8,9,10};
for (int i = 0; i < sizeof(u) / 2; i++)
swap(&u[i], &(&u)[1][-i - 1]);
}
这种在最后访问数组的方法是否存在缺陷?
最佳答案
C标准未定义(&array)[1]
的行为。
考虑&array + 1
。这是由C标准定义的,其原因有两个:
&array
是指向单个对象的指针(本身就是数组,但是指针算法是针对数组的指针,而不是元素的指针)。 因此,
&array + 1
被定义为指针算法,该算法指向刚超出array
末尾的位置。但是,根据下标运算符的定义,
(&array)[1]
是*(&array + 1)
。虽然定义了&array + 1
,但未将*
应用于它。 C 2018 6.5.6 8关于指针算术的结果明确告诉我们:“如果结果指向数组对象的最后一个元素之后,则不应将其用作被评估的一元*
运算符的操作数。”由于大多数编译器的设计方式,问题中的代码可能会根据您的需要移动数据。但是,这不是您应该依靠的行为。您可以使用
char *End = array + sizeof array / sizeof *array;
获得指向数组最后一个元素的良好指针。然后,您可以使用End[-1]
引用最后一个元素,使用End[-2]
引用倒数第二个元素,依此类推。
关于c - 从C中的结尾访问数组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61560339/