3

在 Visual Studio C++ 版本 9(可能还有其他版本)中,以下代码:

int a = sizeof(void);
void const *b = static_cast<void const *>("hello world");
b += 6;

生成这些 错误

error C2070: 'void': illegal sizeof operand
error C2036: 'const void *' : unknown size

此代码在 GCC 下工作,GCC 将其sizeof(void)视为1.

有没有办法绕过这个限制,因为char *为了指针算术的目的而显式地强制转换会增加混乱(void *被很好地识别并用作指向原始内存的无类型指针)。

更新0

  • 请注意,我很清楚该标准的存在。
  • 想做原始指针算术。
  • 我要sizeof(void)表明我很清楚这不是1问题的原因。
  • 该代码示例只是为了演示生成错误所需的内容。
  • 我知道这不是一种“正常”的使用方式void,但这是 C,并且会发生这些事情。
  • 是的,人们需要在底层做这件事。我不是在追求为什么,我在追求如何。如果你想知道为什么,看看一些内核源代码,或者你友好的 glibc。

更新1

这个问题似乎引起了很大的混乱。问题不在于为什么拥有sizeof(void) == 1不标准,而在于如果不是标准该怎么办。

在要进行单字节指针运算的情况下,事实证明强制转换为char *是正确的答案,不是因为*(void *)没有大小,而是因为标准实际上保证*(char *)是 always 1。因此,对于原始指针算术的目的,使用char *总是正确的,并且与 GCC 扩展一致。void *

为了进一步强调这一点,void *对于指向无类型内存的指针是正确的选择,并且对于原始指针算术char *来说是正确的类型。

4

8 回答 8

18

增加一个指针在技术上应该增加它所指向的东西的大小。虚无指向虚无,所以大小不详。

对于一些编译器来说,让你增加 void 指针是一个很好的选择。

投射很烦人,因为您必须将其投射到另一个指针,然后返回,或者做一些尴尬的事情,比如(*(char *)&voidptr) += 6

就个人而言,我只是将其声明为char *用于算术目的

于 2009-12-08T03:24:51.753 回答
10

在 C 语言sizeof中不能应用于不完整的类型。void是一个不完整的类型,这就是为什么你不能将它用作sizeof.

C 也不支持指针的指针算术void *。为了与指针算术一起使用,指针必须指向对象类型,但void事实并非如此。

GCC 允许两者都作为奇怪的语言扩展。

于 2009-12-08T03:27:43.670 回答
6

void *意味着“指向未知的指针”

因此,将 6 添加到 void 指针是未定义的,因为您要求编译器将指针推进“6 个未知对象的大小”。

你不应该这样做。

于 2009-12-08T03:32:11.413 回答
3

这里有两个不同的问题。第一个为void,第二个为void*。它们是不同的类型,除了名称之外几乎没有共同点。

void主要用于函数声明/定义(作为返回类型或表示“不带参数”)。你不可能有一个 type 的对象void。曾经。所以很难看出需要找出那个不存在的物体的大小。 GCC 的行为是非标准的,并且是有意的扩展. 但是,我相信他们之所以选择sizeof(void) == 1是因为 C++ 标准要求每个对象至少占用一个字节的空间。

void*意思是“指向真实数据的指针,但没有相关的类型信息”。完全有可能拥有void*; 你会经常遇到他们。然而,因为类型信息被忽略了,所以你不能对指针进行太多操作。这是设计使然,因为如果你不知道你拥有什么,你真的不知道你能用它做什么。

但是,如果您想将内存视为字节的集合,则char*可以这样做。Achar是一个字节,无处不在。一串字节是一个char*. 如果您觉得这很奇怪,请使用byte*(您定义byte为类似 的地方unsigned char)。

于 2009-12-08T09:09:20.527 回答
2

我至少可以在第一行看到错误 - 你有 sizeof(void),它应该是 sizeof(void*),不是吗?

于 2009-12-08T03:22:10.620 回答
1

对于纯粹指向原始数据并将该指针增加一个数据块占用的字节数,我总是使用char *. 然后,一旦我需要将其视为特定的东西,我就会将指针重新转换为相关的数据结构指针。递增 avoid *在编译器之间是不可移植的。

于 2009-12-08T04:29:10.027 回答
1

void * 被很好地识别并用作指向原始内存的无类型指针。

正确的。没有类型意味着也没有大小。

于 2009-12-09T08:47:02.390 回答
-3

看起来正确的答案char *用于指针算术,因为sizeof(char)它总是被定义为 1,并且在任何平台上都是最精细的可寻址粒度。

所以简而言之,没有办法绕过限制,char *实际上是正确的方法。

Matthias Wandel正确的答案,但有不同的理由。

于 2009-12-08T07:05:44.547 回答