以下代码是否有效?
int* arr = new int[2];
std::cout << &arr[0x100];
这被认为是一种良好的做法,还是以常规方式添加偏移量会更清晰?
编辑:通过&#34;工作&#34;我的意思是它应该在0x100打印理论成员的指针。基本上如果这相当于&#34; std :: cout&lt;&lt; ((unsigned int)arr + 0x100 * sizeof(int));&#34;。
答案 0 :(得分:1)
使用我的编译器(Cygwin GCC)获取此值的地址与执行指针算法相同,尽管每个都是未定义的行为(UB)。正如Jens在http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html下面的评论中提到的,我发现以下内容对您有所帮助。
值得指出的是,Clang和GCC都指出了C标准未定义的一些行为。我将描述的内容根据标准未定义,并且在默认模式下被这两个编译器视为未定义的行为。
对野外指针和超出界限的取消引用数组访问:取消引用随机指针(如NULL,指向自由内存的指针等)以及访问数组越界的特殊情况是C应用程序中的常见错误希望不需要解释。为了消除这种未定义行为的来源,必须对每个数组访问进行范围检查,并且必须更改ABI以确保范围信息围绕可能受指针算术影响的任何指针。对于许多数字和其他应用程序来说,这将花费极高的成本,并且打破与每个现有C库的二进制兼容性。
指针算术也是UB。所以你有一个地址,但你不能取消引用它的指针。所以根本没有用这个地址。只是获取地址是UB,不应该在代码中使用。
对于越界指针,请参阅此答案: Why is out-of-bounds pointer arithmetic undefined behaviour?
我的示例代码:
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
答案 1 :(得分:0)
在第一行中分配2个整数值。在第二行中,您可以访问此范围之外的内存。这根本不允许。
编辑:这里有一些有趣的评论。但我无法理解,为什么需要引用这样一个简单答案的标准,为什么这里讨论指针运算这么多呢?
从逻辑视图来看,std :: cout&lt;&lt; &amp; arr [0x100]包含3个步骤: 1.访问数组的非现有成员 2.获取现有成员的地址 3.使用非现有成员的地址
如果第一步无效,以下所有内容是否未定义?