c-读取以void*形式传递的char数组,指针递增,然后读取为chars和其他数据类型



因此,为了消除我想从文件(char数组)中读取的标题中的误解(不知道如何在标题中提问),将其作为void*传递,这样我就可以通过增加指针来读取不依赖的数据类型。因此,这里有一个简单的例子,我想在C代码中做什么:

char input[] = "DCkjh";
char* pointer = &input[0];       //lets say 0x00000010 
char type1 = *pointer;           //should be 'D'
pointer += sizeof(char);         //0x00000020
uint16_t value1 = *(uint16_t*)pointer; //should be 0
pointer += sizeof(uint16_t);     //0x00000040
char type2 = *pointer;           //should be 'C'
pointer += sizeof(char);         //0x00000050
uint32_t value2 = *(uint32_t*)pointer; //should be 1802135552

这只是为了教育目的,所以我只想知道这是否可能,或者是否有办法实现同样的目标或类似的事情。此外,如果能知道它的速度,那就太好了。只保留数组并在读取字符时对其进行移位会更快吗?还是实际上更快?

编辑:对c代码进行编辑,并将void*更改为char*;

这在两个方面是错误的:

  1. void不完全类型不能完成不完全类型是没有已知大小的类型。为了进行指针运算,必须知道大小。取消引用指针也是如此。一些编译器将char的大小归因于void,但这是一个永远不应该依赖的扩展。增加指向void的指针是错误的,无法工作。

  2. 您所拥有的是一个char数组。通过不同类型的指针访问此数组会违反严格别名,不允许这样做。

    这实际上不是您当前代码所做的——看看这一行:

    uint32_t value2 = (int)*pointer; //should be 1802135552
    

    您只是将单字节(假设您的指针指向char,请参阅我的第一点)转换为uint32_t。你可能的意思

    uint32_t value2 = *(uint32_t *)pointer; //should be 1802135552
    

    可能会做您期望的事情,但在技术上是未定义的行为。

第二点的相关参考文献如N1570中的§6.5 p7,C11:的最新草案

对象的存储值只能由具有以下值之一的左值表达式访问以下类型:
--与对象的有效类型兼容的类型,
–与对象的生效类型兼容的一个类型的限定版本,
--是与对象,
-一个类型,它是与对象的有效类型,
--在其成员(递归地,包括子聚合或包含联合的成员),或
--字符类型。

这个非常严格的规则的理由是,例如它使编译器能够基于不同类型的两个指针(char *除外)可以从不别名的假设进行优化。其他原因包括某些平台上的对齐限制

即使在取消引用之前将代码修复为将指针强制转换为正确的类型(如int*),也可能存在对齐问题。例如,在某些体系结构中,如果4字节的int没有与4字节的字边界对齐,则根本无法读取。

一个肯定有效的解决方案是使用这样的东西:

int result;
memcpy(&result, pointer, sizeof(result));

更新:

在问题的更新代码中

uint16_t value1 = *(uint16_t*)pointer;

恰好违反了严格别名。这是无效代码。

有关更多详细信息,请阅读答案的其余部分。


初始版本:

从技术上讲,首先不允许取消引用void指针。

引用C11,第6.5.3.2章

[…]如果操作数指向函数,则结果为功能指示符;如果它指向一个对象,则结果为指定对象如果操作数具有类型"指向类型",则结果具有类型"类型"。[…]

但是,void是一个永远不完整的类型,因此存储大小未知,因此不可能取消引用。

gcc扩展允许您取消引用void指针并对其执行算术运算,将其视为char指针的别名,但最好不要对此进行回复。请将指针强制转换为字符类型或实际类型(或兼容类型),然后继续取消引用。

也就是说,如果将指针本身强制转换为字符类型以外的其他类型,或者与原始指针不兼容的类型,则会违反严格的别名规则。

如第6.5章所述,

对象的存储值只能由具有以下值之一的左值表达式访问以下类型的

--与对象的有效类型兼容的类型

--与对象的有效类型兼容的类型的合格版本,

--一个类型,它是与对象,

--一个类型,它是与的限定版本相对应的有符号或无符号类型物体的有效类型

--一种聚合或并集类型,在其成员(递归地,包括子集合或包含联盟的成员),或

--字符类型。

和,第6.3.2.3章

[….]当指向对象的指针转换为指向字符类型的指针时,结果指向对象的最低寻址字节。的连续增量结果,直到对象的大小,产生指向对象剩余字节的指针。

最新更新