c - 指向数组第一个元素之前的指针
问题描述
在 C 语言中说,当指针指向同一个数组或该数组末尾的一个元素时,算术和比较是明确定义的。那么在数组的第一个元素之前呢?只要我不取消引用它就可以吗?
给定
int a[10], *p;
p = a;
(1) 写字合法--p
吗?
p-1
(2)用表达式书写是否合法?
(3) 如果 (2) 没问题,我可以断言p-1 < a
吗?
对此存在一些实际问题。考虑一个reverse()
反转以 . 结尾的 C 字符串的函数'\0'
。
#include <stdio.h>
void reverse(char *p)
{
char *b, t;
b = p;
while (*p != '\0')
p++;
if (p == b) /* Do I really need */
return; /* these two lines? */
for (p--; b < p; b++, p--)
t = *b, *b = *p, *p = t;
}
int main(void)
{
char a[] = "Hello";
reverse(a);
printf("%s\n", a);
return 0;
}
我真的需要检查代码吗?
请从语言律师/实践的角度分享您的想法,以及您将如何应对这种情况。
解决方案
(1) 写--p是否合法?
它是“合法的”,因为 C 语法允许它,但它会调用未定义的行为。为了在标准中找到相关部分,--p
等价于p = p - 1
(除了p
只评估一次)。然后:
C17 6.5.6/8
如果指针操作数和结果都指向同一个数组对象的元素,或者超过数组对象的最后一个元素,则计算不应产生溢出;否则,行为未定义。
评估调用未定义的行为,这意味着您是否取消引用指针并不重要 - 您已经调用了未定义的行为。
此外:
C17 6.5.6/9:
当两个指针相减时,都应指向同一个数组对象的元素,或者指向数组对象的最后一个元素;
如果您的代码违反 ISO 标准中的“应”,它会调用未定义的行为。
(2) 在表达式中写 p-1 是否合法?
与 (1) 相同,未定义的行为。
至于这在实践中如何导致问题的示例:假设数组放置在有效内存页面的最开头。当您在该页面之外递减时,可能会出现硬件异常或指针陷阱表示。对于微控制器来说,这并不是完全不可能的情况,尤其是当它们使用分段内存映射时。
推荐阅读
- javascript - jQuery中nextAll()和siblings()的区别
- python - 未找到“产品”的反向。“产品”不是有效的视图函数或模式名称
- android - 添加 RecyclerView 项目总计
- python-3.x - RuntimeError:为 ResNet 加载 state_dict 时出错:
- postgresql - 向工作查询添加额外的 WHERE 子句以进一步按百分比排序
- c - 如何在C中搜索trie中的所有字符串
- python - 高效地从生成器中提取数据
- java - 如何为具有多种类型的项目设计休息端点?
- mysql - 如果对其他列进行查询,则获取使用计数填充的计数总和 - 到右侧的最后一列
- javascript - 隐藏在 Javascript 中后,按钮未显示