显然,取消引用无效指针会导致未定义的行为.但是如果只是在指针变量中存储无效的内存地址呢?
请考虑以下代码:
const char* str = "abcdef";
const char* begin = str;
if (begin - 1 < str) { /* ... do something ... */ }
Run Code Online (Sandbox Code Playgroud)
表达式begin - 1求值为无效的内存地址.请注意,我们实际上并没有取消引用此地址 - 我们只是在指针算法中使用它来测试它是否有效.尽管如此,我们仍然需要将无效的内存地址加载到寄存器中.
那么,这是不确定的行为吗?我从来没有想过,因为很多指针算法似乎依赖于这种事情,而指针实际上只是一个整数.但最近我听说即使将无效指针加载到寄存器中的行为也是未定义的行为,因为某些架构会自动抛出总线错误或者其他内容.任何人都可以向我指出C或C++标准的相关部分,无论哪种方式解决这个问题?
它看起来像下面的程序计算一个无效的指针,因为NULL除了赋值和比较相等之外没有任何好处:
#include <stdlib.h>
#include <stdio.h>
int main() {
char *c = NULL;
c--;
printf("c: %p\n", c);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
然而,似乎GCC或Clang针对未定义行为的警告或工具都没有说这实际上是UB.这个算术实际上是否有效,而且我太迂腐了,或者这是我们应该报告的检查机制的缺陷吗?
测试:
$ clang-3.3 -Weverything -g -O0 -fsanitize=undefined -fsanitize=null -fsanitize=address offsetnull.c -o offsetnull
$ ./offsetnull
c: 0xffffffffffffffff
$ gcc-4.8 -g -O0 -fsanitize=address offsetnull.c -o offsetnull
$ ./offsetnull
c: 0xffffffffffffffff
Run Code Online (Sandbox Code Playgroud)
似乎很好地记录了Clang和GCC使用的AddressSanitizer更侧重于解除坏指针的引用,所以这很公平.但其他检查也没有抓住它: - /
编辑:我问这个问题的部分原因是-fsanitize标志能够动态检查生成的代码中的良好定义.这是他们应该抓住的东西吗?
如果将地址取一个数组的末尾是合法的,那么如果数组地址的最后一个元素是0xFFFFFFFF?
这段代码将如何工作:
for (vector<char>::iterator it = vector_.begin(), it != vector_.end(); ++it)
{
}
Run Code Online (Sandbox Code Playgroud)
编辑:
我在这里读到在提出这个问题之前它是合法的:我可以采用数组的一个接一个元素的地址吗?
嗨,我很困惑,得到下面的解释,有人可以解释给我吗?提前致谢.
#include<stdio.h>
int main(){
char *arr,c;
arr = &c;
arr++;
*arr = 'a';
arr++;
*arr = 'b';
arr++;
*arr = 'c';
arr--;
arr--;
printf("\narr 1 = %c",arr);
printf("\narr 2 = %c",arr[1]);
printf("\narr 3 = %c",arr[2]);
getch();
return 1;
}
Run Code Online (Sandbox Code Playgroud)
输出为:
arr 1 = a
arr 2 = b
arr 3 = c
但如果改变线:
printf("\narr 1 = %c",arr);
Run Code Online (Sandbox Code Playgroud)
同
printf("\narr 1 = %c",arr[0]);
Run Code Online (Sandbox Code Playgroud)
现在输出为:
arr 1 =
arr 2 = b
arr 3 = c
为什么'a'没有印刷.?
*对于所有那些质疑程序编码不好的人来说..我知道使用像这样的指针不是一个好的编码实践,但我的问题是为什么arr [0]不打印任何地方,如arr [1]&arr [ …