c++ - C++ 指针移动
问题描述
int main()
{
char *A[] = { "abcx", "dbba", "cccc"};
char var = *(A+1) - *A+1;
cout << (*A + var);
}
嗨,代码给出了输出 bba。我无法理解,var 的整数值是如何变成 6 的。 var 值是按什么顺序求解的。请解释。提前致谢。
解决方案
A 是指向字符数组的指针数组。又名,字符串。由于 4 个字符串文字,每个数组有 5 个字符长,每个字符串都有一个隐藏的空终止符。
因为你很幸运,而且你的编译器做了简单的事情,所以字符文字一个接一个地放入程序中。
所以 *A 是第一个数组的地址。*(A+1) 是第二个数组的地址。减去它们,即为 5。为 6 加 1。
这种 C 代码被混淆了。它也可能很危险。即使您很确定后面还有第二个数组,我也不会依赖于通过数组外部的指针进行访问。假设这只会导致痛苦。和苦难。
因为*A + var
当var
大于数组大小时是未定义的行为。在这种情况下,有效数组大小为 5,因此有效值为var
0..4。
未定义的行为意味着允许编译器的优化器假定它不会发生。因为如果您的程序DID具有未定义的行为,则它不会是已定义的程序,并且会自动为WRONG。所以很明显你永远不会那样做。哈。
这是一些修改后的代码,希望能更好地解释:
#include <iostream>
int main() {
char *A[] = {"abcx", "dbba", "cccc"};
char var = *(A + 1) - *A + 1;
std::cout << (void *)*A << std::endl;
std::cout << (void *)*(A + 1) << std::endl;
std::cout << (*A + var) << std::endl;
return 0;
}
运行它:
0x402010
0x402015
bba
这些是我特定机器上的内存地址,你的可能不同。但重要的是它们有 5 个字节不同。
现在我将使用一个名为xxd
. 你可以找到其他好的。如果我将二进制可执行文件转储为十六进制并搜索,dbba
我会找到一行:
00002010: 6162 6378 0064 6262 6100 0000 011b 033b abcx.dbba......;
哦等等,让我在没有优化的情况下重建它。明白我说这是有风险的生意是什么意思吗?
00002010: 6162 6378 0064 6262 6100 6363 6363 0000 abcx.dbba.cccc..
优化器已经从二进制文件中完全删除了第三个数组元素,因为没有人使用它。
如果我们编写的代码稍有不同,优化器可能会同时删除第二个和第三个数组元素,并且您会尝试打印二进制垃圾数据。
推荐阅读
- html - 悬停时的 SVG 不进行过渡
- java - Java - for 循环相关查询
- r - 打印 add1() 的进度报告
- java - 当我尝试在 recyclerview 中搜索时,我在代码中做错了什么?
- ios - (iOS) viewport-fit=cover 元标记不能完美地与导航栏配合使用
- python - Sqlite“OperationalError:靠近“05”:语法错误”
- database - SQLite:从路径列表创建目录结构表
- reactjs - 异步等待未通过 onupload 进度回调捕获 401 axios
- nltk - 使用 NLTK 以三列格式读取自定义语料库以进行 pos 标记
- java - 在来自 Micronaut 休息端点的 JSON 中包含 null 和空属性