C++ static_cast从int*到void*到char* - 你能帮我理解这段代码吗?

use*_*609 6 c++ static-cast

我是C++的初学者,我对理解一些代码有疑问.

我做了一个练习,写了返回大小的功能int,并且不使用sizeof()reinterpret_cast.有人给了我解决方案,但我不明白它是如何工作的.你能帮我理解一下吗?这是代码:

int intSize() {
  int intArray[10];
  int * intPtr1;
  int * intPtr2;

  intPtr1 = &intArray[1];
  intPtr2 = &intArray[2];

  //Why cast int pointer to void pointer?
  void* voidPtr1 = static_cast<void*>(intPtr1);

  //why cast void pointer to char pointer?
  char* charPtr1 = static_cast<char*>(voidPtr1);

  void* voidPtr2 = static_cast<void*>(intPtr2);
  char* charPtr2 = static_cast<char*>(voidPtr2);

  //when I try to print 'charPtr1' there is nothing printed
  //when try to print charPtr2 - charPtr1, there is correct value shown - 4, why?
  return charPtr2 - charPtr1;
}
Run Code Online (Sandbox Code Playgroud)

要总结一下我不明白的是,为什么要改int*void*,然后char*做这个任务?为什么我们有结果时,我们减去charPtr2charPtr1,但上什么都没有的时候尽量只打印charPtr1

Com*_*sMS 17

首先,永远不要在现实世界的代码中这样做.你会吹掉你的腿,看起来像个白痴,所有酷孩子都会嘲笑你.

话虽如此,这是它的工作原理:基本思想是int的大小等于int数组中两个元素之间的偏移量(以字节为单位).数组中的Int是紧密打包的,所以第二个int的开头就在第一个int的结尾之后:

int* intPtr1 = &intArray[0];
int* intPtr2 = &intArray[1];
Run Code Online (Sandbox Code Playgroud)

这里的问题是,当减去两个int指针时,你不会得到字节差异,而是ints的差异.所以,intPtr2 - intPtr11的,因为他们相距1个INT.

但是我们使用C++,所以我们可以指向任何东西!因此,我们不是使用int指针,而是将值复制到char指针,其大小为1个字节(至少在大多数平台上).

char* charPtr1 = reinterpret_cast<char*>(intPtr1);
char* charPtr2 = reinterpret_cast<char*>(intPtr2);
Run Code Online (Sandbox Code Playgroud)

差异charPtr2 - charPtr1是以字节为单位的大小.指针仍然指向与之前相同的位置(即数组中第二个和第一个int的开始),但现在将以大小而char不是大小来计算差异int.

由于练习不允许reinterpret_cast你将不得不诉诸另一个技巧.你不能static_castint*char*直接.这是C++保护你做一些愚蠢行为的方法.诀窍是先施展void*.你可以static_cast任意的指针类型void*,并从void*任何指针类型.


Rup*_*Rup 4

这是重要的一点:

intPtr1 = &intArray[1];
intPtr2 = &intArray[2];
Run Code Online (Sandbox Code Playgroud)

这将创建两个指向数组中相邻整数的指针。这两个指针之间的距离是您尝试检索的整数的大小。然而,指针算术的工作方式是,如果你减去这两个值,那么编译器将返回以整数表示的大小,该大小始终为 1。

因此,您接下来要做的就是将它们重新转换为字符指针。每个字符(或事实上)都是 1 个字节,因此这两个作为字符指针的指针之间的差异将为您提供以字节为单位的答案。这就是为什么你要转换为字符指针并进行减法。

至于via void*- 这是为了避免使用reinterpret_cast。不允许您直接从 a 转换int*为 a char*with static_cast<>,但是 viavoid*会消除此限制,因为编译器不再知道它以int*. 您也可以只使用 C 风格的强制转换,(char*)(intPtr1).