void时指针算法未知大小
在Visual Studio C ++版本9(也可能是其他版本)中,代码如下:
int a = sizeof(void); void const *b = static_cast("hello world"); b += 6;
生成这些 错误 :
error C2070: 'void': illegal sizeof operand error C2036: 'const void *' : unknown size
此代码在GCC下工作,它将sizeof(void)
视为1
。
有没有办法绕过这个限制,因为为了指针运算而显式地转换为char *
会增加混淆( void *
被很好地识别并用作指向原始内存的无类型指针)。
Update0
- 请注意,我很清楚标准的存在。
- 我想做原始指针算术。
- 我把
sizeof(void)
表示我很清楚它不是1
的原因是问题的原因。 - 代码示例仅用于演示生成错误所需的内容。
- 我知道这不是使用
void
的“正常”方式,但这是C,这些事情发生了。 - 是的,人们需要在低级别这样做。 我不是在追求原因,我是在追求如何。 如果你想知道原因,请查看一些内核源代码或友好的glibc。
UPDATE1
看来这个问题引起了很大的混乱。 问题不在于为什么 sizeof(void) == 1
不是标准的,而是什么时候不做。
在要进行单字节指针运算的情况下,事实certificate,转换为char *
是正确的答案,不是因为*(void *)
没有大小,而是因为标准实际上保证*(char *)
永远是1
。 因此,为了原始指针算法的目的, char *
的使用总是正确的,并且与具有GCC扩展的void *
一致。
为了进一步强调这一点, void *
是指向无类型内存的指针的正确选择,而char *
是用于转换为原始指针算法的正确类型。
从技术上讲,增加一个指针可以通过它指向的任何大小来增加它。 无效点无所谓,因此大小未知。
对于某些编译器来说,它是一个让你增加void指针的精确性。
转换很烦人,因为你必须将它转换为另一个指针,然后返回,或做一些尴尬的事情,如(*(char *)&voidptr) += 6
就个人而言,我只是为了算术而将它声明为char *
在C语言中, sizeof
不能应用于不完整类型。 void
是一个不完整的类型,这就是为什么你不能将它用作sizeof
操作数。
C中也不支持void *
指针的指针算法。为了与指针算法一起使用,指针必须指向对象类型,而void
不是。
GCC允许两者作为奇怪的语言扩展。
void *
意味着“指向未知的指针”
因此,未定义向void指针添加6,因为您要求编译器将指针推进“6个未知对象的大小”。
你不应该这样做。
这里有两个不同的问题。 第一个是void
,第二个是void*
。 它们是不同的类型,并且在名称旁边几乎没有共同之处。
void
主要用于函数声明/定义(作为返回类型或表示“不带参数”)。 你永远不可能有一个void
类型的对象。 永远。 因此很难看出需要找出不存在的对象的大小。 海湾合作委员会的行为是非标准的,是故意的延伸 。 但是,我相信他们选择了sizeof(void) == 1
因为C ++标准要求每个对象占用至少一个字节的空间。
void*
表示“指向实际数据的指针,但没有相关的类型信息”。 完全可能void*
; 而且你会遇到很多。 但是,因为忽略了类型信息,所以无法操纵指针。 这是设计,因为如果你不知道你有什么,你真的不知道你可以用它做什么。
但是如果你想将内存视为一个字节集合,那么char*
会这样做。 char
是一个字节,无处不在。 字符串是char*
。 如果您发现这很奇怪,请使用byte*
(其中您将byte
定义为unsigned char
类的东西)。
我至少可以在第一行看到错误 – 你有sizeof(void),它应该是sizeof(void *),不是吗?
对于纯粹指向原始数据并将该指针递增一个数据块占用的字节数,我总是使用char *
。 然后,一旦我需要将其视为特定的东西,我就会重新指向相关数据结构指针。 增加void *
在编译器中不可移植。
void *被很好地识别并用作原始内存的无类型指针。
正确。 没有类型意味着没有大小。
看起来正确的答案是使用char *
作为指针算法,因为sizeof(char)
总是被定义为1,并且在任何平台上都是最好的可寻址粒度。
简而言之,没有办法绕过限制, char *
实际上是正确的方法。
马蒂亚斯·万德尔有正确的答案,但有不同的理由。