C++数组超出范围访问以计算指针有效?
C++ Array out of Range access to calculate pointer valid?
以下代码是否保证有效?
int* arr = new int[2];
std::cout << &arr[0x100];
这被认为是好的做法,还是以常规方式添加偏移量会更干净?
编辑:通过"工作",我的意思是它应该在0x100打印指向理论成员的指针。基本上,如果这等价于"std::cout <<((unsigned int)arr + 0x100*sizeof(int));"。
使用我的编译器(Cygwin GCC)获取此值的地址与执行指针算术相同,尽管每个都是未定义的行为(UB)。正如 Jen 在下面的评论中提到的,在 http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html,我发现以下内容很有帮助。
同样值得指出的是,Clang和GCC都确定了C标准未定义的一些行为。我将描述的内容根据标准都是未定义的,并且被这两个编译器在其默认模式下视为未定义的行为。
取消引用野生指针和越界数组访问:取消引用随机指针(如 NULL、指向释放内存的指针等)和越界访问数组的特殊情况是 C 应用程序中的常见错误,希望不需要解释。为了消除这种未定义行为的来源,必须对每个数组访问进行范围检查,并且必须更改 ABI,以确保范围信息遵循任何可能受指针算术影响的指针。对于许多数值和其他应用程序来说,这将产生极高的成本,并且会破坏与每个现有 C 库的二进制兼容性。
指针算法也是 UB。所以你有一个地址,但你不能取消引用指向它的指针。所以拥有这个地址真的没有用。仅获取地址是 UB,不应在代码中使用。
有关越界指针,请参阅此答案: 为什么越界指针算术是未定义的行为?
我的示例代码:
int* arr = new int[2];
std::cout << arr << std::endl;
std::cout << &(arr[0])<< std::endl;
std::cout << &(arr[1])<< std::endl;
std::cout << &arr[0x100] << std::endl; // UB, cannot be dereferenced
std::cout << &arr[256] << std::endl; // cannot be dereferenced, so no use in having it
std::cout << arr + 0x100; // UB here too, no use in having this address
示例输出:
0x60003ae50
0x60003ae50
0x60003ae54
0x60003b250
0x60003b250
0x60003b250
在第一行中分配 2 个整数值。在第二行中,您访问此范围之外的内存。这是完全不允许的。
编辑:这里有一些有趣的评论。但我不明白,为什么需要引用这么简单答案的标准,为什么这里讨论这么多指针算术?
从逻辑角度来看,std::cout <<&arr[0x100] 包含 3 个步骤: 1. 访问数组中不存在的成员 2. 获取不存在成员的地址 3. 使用不存在的成员的地址
如果第一步无效,以下不是所有未定义吗?
- 通过指针算法计算数组长度
- 使用指针计算堆栈问题的大 O 表示法
- C++ 函数指针的计算结果为 1
- 如何计算一系列指针的内容长度
- 计算双指针数组的长度
- 指针警告(并行计算)
- C++数组超出范围访问以计算指针有效?
- 使用指针计算三角形各点之间的距离
- 通过使用指针/引用,在C++中使用向量加快计算速度
- (指针)降低测试分数后计算平均功能的问题
- 当短路禁用常量表达式的计算时,是否允许在常量表达式中读取"一过一"指针
- 如何计算指向不同矢量数组中特定对象的指针的出现次数
- 创建 COM 接口指针在开发计算机上有效,但会导致其他计算机上的应用程序崩溃
- 如何正确使用指针来计算平均值
- 使用指针和结构C 计算两个点之间的距离,分割故障问题
- 如何在编译期间计算数组大小(不接受指针)
- 正在计算包含对象的此指针
- 64位计算机上的int大小和int指针大小
- 如何计算并返回指向max元素的指针的值?C++
- 使用nullptr计算指针偏移是否安全?