首页 > 解决方案 > C++ 指针移动

问题描述

int main() 
{ 
    char *A[] = { "abcx", "dbba", "cccc"}; 
    char var = *(A+1) - *A+1; 
    cout << (*A + var); 
} 

嗨,代码给出了输出 bba。我无法理解,var 的整数值是如何变成 6 的。 var 值是按什么顺序求解的。请解释。提前致谢。

标签: c++

解决方案


A 是指向字符数组的指针数组。又名,字符串。由于 4 个字符串文字,每个数组有 5 个字符长,每个字符串都有一个隐藏的空终止符。

因为你很幸运,而且你的编译器做了简单的事情,所以字符文字一个接一个地放入程序中。

所以 *A 是第一个数组的地址。*(A+1) 是第二个数组的地址。减去它们,即为 5。为 6 加 1。

这种 C 代码被混淆了。它也可能很危险。即使您很确定后面还有第二个数组,我也不会依赖于通过数组外部的指针进行访问。假设这只会导致痛苦。和苦难。

因为*A + varvar大于数组大小时是未定义的行为。在这种情况下,有效数组大小为 5,因此有效值为var0..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..

优化器已经从二进制文件中完全删除了第三个数组元素,因为没有人使用它。

如果我们编写的代码稍有不同,优化器可能会同时删除第二个和第三个数组元素,并且您会尝试打印二进制垃圾数据。


推荐阅读