繁体   English   中英

C语言中任意内存的类型

[英]A type for arbitrary memory in C

这是参考这个问题

如何正确实现c malloc / realloc函数?

接受的答案提到可以使用char数组对任意内存池进行建模。

但是,对该已接受答案的评论之一指出

没有分配存储时间的char数组只能以字符类型作为别名。 换句话说,它不能也不应用作任意内存

这个对吗? 如果是这样,那么可以使用什么呢? 我想避免使用alloc或任何特定的OS调用-所以我对这个问题持对称态度。

周围有不同的问题。 首先,如@Magisch的答案所示,相关问题是返回一个悬空指针,导致未定义行为和一般执行错误。

第二个与@ ^ *#(此处为检查)严格的别名规则相关。 当您将字符数组用作大缓冲区以从中分配任何类型时,如果您确保正确对齐,则普通编译器会生成正确的代码。 毕竟,这是他们必须实现mallocreallocfree例程的方式。 而且,由于它们是托管环境 (C标准库)的一部分,因此编译器开发人员还不足以禁止其使用。

但是C标准在这里更加严格。 您应该在此处阅读我对类似问题的答案,尤其是@EOF对它的评论:

您不能将声明为char []的对象的一部分打包为其他类型(字符类型除外)的对象,因为它们确实具有声明的类型...这意味着从技术上讲,您不能在纯C语言中实现malloc()

别名是指严格的别名规则该规则控制如何允许编译器使用寄存器。 如果您具有指向同一存储器位置的不同类型的指针,则在通过另一种指针类型进行读取时可能不会注意到通过一种指针类型完成的写入,因为允许编译器将数据缓存在寄存器中。

当您实现一个内存池时,这个问题通常是没有解决的,因为该池实现不会对内存进行读/写操作。

如果要使用任意类型,那么最安全的选择是联合。 它不仅会“击败”严格的别名规则,还将确保正确的对齐方式。 请记住, malloc和Friends确保适合任何类型的对齐方式,而auto不适合。

问题是对齐。 在具有对齐限制的处理器上, char数组可能不会从适合于存储较大对象(例如intdouble的地址开始。

为了安全起见,您需要确保char数组对于任何类型都正确对齐。 如果您使用的是C11编译器,则可以像这样强制对齐

#include <stddef.h>
#include <stdalign.h>

_Alignas(max_align_t) char buffer[SIZE];

对于较旧的编译器, __attribute__((aligned(SIZE)))可能是一个解决方案。 否则,您需要查找强制对齐的#pragma

而且,正如在各种注释/答案中所讨论的,您绝对应该使用-fno-strict-aliasing选项禁用严格的别名优化。 如果该选项(或等效选项)不存在,则需要确定依赖于严格别名规则的优化级别,并且仅使用较低的优化级别。

我认为他指出的问题是,如果您静态分配一个char类型的数组,然后使用像gcc这样的现代,类似于桌面的C编译器来编译您的库,则无法轻松地将该区域的内容转换为另一种类型。 因为这样编译器将基于指针别名执行优化并将所有事情搞砸,因此请参阅“严格的别名规则”

只需确保您的编译器不使用严格的别名就可以了。 例如,市场上没有一个普通的嵌入式系统编译器可以做到这一点。

使用gcc时,您将编译为-fno-strict-aliasing 始终为可能导致此类问题的代码启用警告可能会很有用-Wstrict-aliasing

附带说明一下,将uint8_t用作泛型类型更有意义,因为与char不同,它是完全明确的:它没有签名,并且大小是众所周知的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM