使用数组的地址获取过期指针
Obtaining a past-the-end pointer using the address of an array
在C和C++中,使用结束指针来编写可以在任意大数组上操作的函数通常很有用。C++提供了一个std::end
重载,使之更容易实现。另一方面,在C中,我发现这样定义和使用宏并不罕见:
#define ARRAYLEN(array) (sizeof(array)/sizeof(array[0]))
// ...
int a [42];
do_something (a, a + ARRAYLEN (a));
我还看到了一个指针算术技巧,用来让这样的函数在单个对象上操作:
int b;
do_something (&b, &b + 1);
我突然想到,数组也可以做类似的事情,因为C(我相信C++)认为它们是"完整的对象"。给定一个数组,我们可以在它之后立即派生一个指向数组的指针,取消对该指针的引用,并在对数组的引用上使用数组到指针的转换,以获得原始数组的结束指针:
#define END(array) (*(&array + 1))
// ...
int a [42];
do_something (a, END (a));
我的问题是:在取消引用指向不存在的数组对象的指针时,此代码是否表现出未定义的行为我很感兴趣的是C和C++的最新修订版对这段代码的看法(不是因为我打算使用它,因为有更好的方法可以获得相同的结果,而是因为这是一个有趣的问题)。
我在自己的代码中使用过它,作为(&arr)[1]
。
我确信它是安全的。数组到指针的衰减不是"左值到右值的转换",尽管它以左值开始,以右值结束。
这是未定义的行为。
CCD_ 3属于CCD_。
CCD_ 5属于CCD_。(注意,这不是数组到指针的转换)
&a + 1
也是pointer to array of 42 int
类型
5.7p5状态:
将具有整型的表达式添加到指针或从指针中减去时,结果具有指针操作数的类型。如果指针操作数指向数组对象的元素,否则为[…],则行为为未定义
指针不指向数组对象的元素。它指向一个数组对象。因此,"否则,行为是未定义的"是正确的。行为是不明确的。
这是C中未定义的行为,除非指针本身是包含更多元素的更大对象的一部分,否则取消引用指向现有对象之外的指针总是如此。
但是使用&array + 1
的基本思想是正确的,只要array
是左值。(有些情况下数组不是lvalue。)在这种情况下,这是一个有效的指针操作。现在,要获得指向第一个元素的指针,只需将其强制转换回基类型即可。在你的情况下,那将是
(int*)(&array + 1)
指向数组的指针值保证与指向其第一个元素的指针值相同,只是类型不同。
不幸的是,我看不出有什么方法可以使这样一个表达式类型不可知,这样你就可以把它放在一个通用宏中,除非你转换为void*
。(例如,您可以使用gcc typeof
扩展)所以你最好坚持使用便携式(array)+ARRAYLEN(array)
,它应该在所有情况下都能工作。
在一个奇怪的角落情况下,作为struct
的一部分并作为函数的右值返回的数组不是左值。我认为这个标准也允许指针算术,但我从来没有完全理解这个结构,所以我不确定它在这种情况下是否有效。
- C++为构建时间获取QDateTime的可靠方法
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 如何使用 < 和 > 命令获取 c++ 中的输入和输出?
- 使用指针从C++中的数组中获取最大值
- 如何获取std::result_of函数的返回类型
- 如何在openssl-ecc中获取十六进制格式的私钥
- 使用Unreal C++获取VR耳机的世界位置/方向
- 获取日期异步信号安全吗?如果在信号处理程序中使用,它会导致死锁吗
- 从C字符串中获取奇怪的字符串长度
- 为什么我的for循环不能正确获取argv
- 从python中调用C++函数并获取返回值
- 如何获取一个数字的前3位
- 获取字符串的长度并将其分配给数组
- 无法获取菜单选择以运行函数.C++
- 数组长度,为什么从命令行获取时不能使用它?
- Boost Spirit,获取迭代器内部语义动作
- 尝试通过OCI例程从Oracle获取blob数据,但出现错误:ORA-01008:并非所有变量都绑定
- 具有默认值的引用获取函数
- 使用数组的地址获取过期指针
- 如何从Internet Explorer获取与cookie相关联的过期日期和标志