如果我创建了一个C模块,它向用户提供一个指向前向声明结构的指针,如下所示:
typedef struct FOO_Obj *FOO_Handle;
Run Code Online (Sandbox Code Playgroud)
如果我然后声明函数原型使用它作为const限定参数:
void FOO_work(const FOO_Handle fooHandle);
Run Code Online (Sandbox Code Playgroud)
如何const应用?
const struct FOO_Obj *FOO_Handle // A
struct FOO_Obj *const FOO_Handle // B
const struct FOO_Obj *const FOO_Handle // C
Run Code Online (Sandbox Code Playgroud)
或者是UB?
此问题涉及遵循 MISRAC:2012 指南的 ISO C99 编码。
\n\n我正在寻找有关 Dir 4.8 \xe2\x80\x9c 的指导如果指向结构或联合的指针从未在翻译单元内取消引用,则该对象的实现应与 Dir 4.12 \ 一起隐藏\xe2\x80\x9d xe2\x80\x9c不应使用动态内存分配\xe2\x80\x9d。
\n\n在 C 中实现抽象数据类型时,通常使用句柄来引用 ADT,该句柄是指向描述 ADT 内部状态的结构的指针。这可以根据 Dir 4.8 使用不透明指针来完成,其优点是内部细节对用户保持隐藏。
\n\n通常,可能存在多个 ADT,因此必须有一种方法来创建多个句柄。这可以通过在初始化函数中为句柄引用的内部细节分配内存来解决,但是,这在 Dir 4.12 下是不允许的。
\n\n另一种选择是初始化例程接收用户提供的指向静态分配句柄的指针,但是,这不能使用不透明指针来完成。
\n\n我在下面说明这个问题。
\n\n Module.h \n\n struct module; \n typedef struct module module_t; /* Module handle is only available to the world as an incomplete type. This allows us to satisfy MISRAC 2012 Dir 4.8.*/\n\n Module.c\n\n #include "module.h"\n struct module\n {\n uint8_t value;\n };\n module_t* module_get_a_handle(void)\n …Run Code Online (Sandbox Code Playgroud) 我正在为我的hashmap数据结构设计一个迭代器接口.目前的设计如下:
// map.h
typedef struct map_iterator map_iterator;
// map.c
struct map_iterator
{
// Implementation details
};
// client.c
map *m = map_new();
map_iterator *it = map_iterator_new(m);
void *key, *value;
while (map_iterator_next(it, &key, &value)) {
// Use key, value
}
map_iterator_free(it);
Run Code Online (Sandbox Code Playgroud)
但是,这需要为迭代器对象分配堆,并且客户端必须记住在迭代器完成时释放迭代器.如果我map_iterator_new在堆栈上返回迭代器,代码如下所示:
// map.h
typedef struct map_iterator
{
// Implementation details
};
// client.c
map *m = map_new();
map_iterator it = map_iterator_new(m);
void *key, *value;
while (map_iterator_next(&it, &key, &value)) {
// Use key, value
}
Run Code Online (Sandbox Code Playgroud)
但是,这要求我将map_iterator结构的定义提供给客户端代码(否则我会得到不完整的类型错误).我想隐藏这个定义并仅提供声明.
有没有办法实现这个目标?本质上,我正在寻找一种方法来告诉客户端代码"这个结构占用了X个字节,因此你可以在堆栈上分配它,但我不会告诉你如何访问它的成员". …
我正在使用传统的C库接口(到C++),将不透明指针公开为
typedef void * OpaqueObject
Run Code Online (Sandbox Code Playgroud)
在图书馆:
OpaqueObject CreateObject()
{
return new OurCppLibrary::Object();
}
Run Code Online (Sandbox Code Playgroud)
这当然为该库的客户提供绝对没有类型安全性.应该将typedef从void指针更改为结构指针的工作方式完全相同,但提供少量类型的安全性?
typedef struct OpaqueObjectInternal_ *OpaqueObject
// OpaqueObjectInternal_ is NEVER defined anywhere in client or library code
Run Code Online (Sandbox Code Playgroud)
是否有任何对齐问题或其他陷阱我现在必须担心我明确指向一个结构,即使我真的没有指向一个?
我目前对 C 结构信息隐藏的概念有点困惑。
这道题的背景是一个嵌入式c项目,对OOP的了解几乎为零。
到目前为止,我总是在相应模块的头文件中声明我的 typedef 结构。因此每个想要使用该结构的模块都知道该结构类型。
但经过 MISRA-C 检查后,我发现了中等严重性警告:MISRAC2012-Dir-4.8 - 结构的实现不必要地暴露给翻译单元。
经过一番研究后,我通过限制结构成员对私有范围的可见访问,发现了 C 结构信息隐藏的概念。
我立即尝试了一个简单的例子,如下所示:
struct_test.h
//struct _structName;
typedef struct _structName structType_t;
Run Code Online (Sandbox Code Playgroud)
struct_test.c
#include "struct_test.h"
typedef struct _structName
{
int varA;
int varB;
char varC;
}structType_t;
Run Code Online (Sandbox Code Playgroud)
主程序
#include "struct_test.h"
structType_t myTest;
myTest.varA = 0;
myTest.varB = 1;
myTest.varC = 'c';
Run Code Online (Sandbox Code Playgroud)
这会产生编译器错误,即对于 main.c,myTest 的大小未知。当然是这样,main.c 只知道 structType_t 类型的结构存在,而没有其他信息。
所以我继续研究并偶然发现了不透明指针的概念。
所以我尝试了第二次尝试:
struct_test.h
typedef struct _structName *myStruct_t;
Run Code Online (Sandbox Code Playgroud)
struct_test.c
#include "struct_test.h"
typedef struct _structName
{
int varA;
int varB;
char varC;
}structType_t;
Run Code Online (Sandbox Code Playgroud)
主程序
#include …Run Code Online (Sandbox Code Playgroud) 我正在设计一个带有公共接口的库,其中包含不透明的结构声明:
lib_public.h:
typedef struct lib_struct lib_struct;
void foo(lib_struct *ptr);
void bar(lib_struct *ptr);
Run Code Online (Sandbox Code Playgroud)
不透明lib_struct的结构隐藏了特定于操作系统的实现细节,因此直接将其放入其中似乎是一个糟糕的设计lib_struct.h。但我仍然想为它编写使用其成员的单元测试。目前,我决定创建一个单独的私有头文件,仅包含结构定义:
lib_struct_linux.h:
struct lib_struct{
int epoll;
int acceptor_socket;
}
Run Code Online (Sandbox Code Playgroud)
因此,实现lib_struct.c和单元测试lib_struct_test.c将包含此标头,如下所示:
lib_struct.c:
#include "lib_struct_linux.h"
//function definition
Run Code Online (Sandbox Code Playgroud)
lib_struct_test.c:
#include "lib_struct_linux.h"
//unit tests
Run Code Online (Sandbox Code Playgroud)
问题是这样的设计看起来很混乱,因为结构体是在一个私有头文件(lib_struct_linux.h)中定义的,而使用该结构体的函数是在另一个公共头文件(lib_public.h)中声明的。函数的定义在另一个实现文件(lib_struct.c)中。
这是常见的方法吗?如果不是,如何才能以更好的方式设计它。
因此,我对各种事物的链接感到有些困惑。对于这个问题,我将重点讨论不透明指针。
我将用一个例子来说明我的困惑。假设我有这三个文件:
主程序
#include <stdio.h>
#include "obj.h" //this directive is replaced with the code in obj.h
int main()
{
myobj = make_obj();
setid(myobj, 6);
int i = getid(myobj);
printf("ID: %i\n",i);
getchar();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
对象文件
#include <stdlib.h>
struct obj{
int id;
};
struct obj *make_obj(void){
return calloc(1, sizeof(struct obj));
};
void setid(struct obj *o, int i){
o->id = i;
};
int getid(struct obj *o){
return o->id;
};
Run Code Online (Sandbox Code Playgroud)
对象文件
struct obj;
struct obj *make_obj(void);
void setid(struct obj *o, int i);
int …Run Code Online (Sandbox Code Playgroud) 有很多关于前向声明和不透明类型的问题,但大多数似乎是从库作者的角度来看的,或者人们试图使用没有指针的不完整类型等。
我正在使用一个接口接受/返回FOO *指针的库。我想确认我不能(或不应该)以某种方式向前声明FOO或FOO *在我的头文件中(它定义了一个带有FOO *成员的结构)。
我知道我可以只#include <library.h>在我的头文件和我的 .c 文件中,但由于这实际上只是一个学习项目,我想得到澄清。(一方面,前向声明似乎是可能的,因为我的结构成员只是一个指针,因此它的大小在不知道是什么的情况下是已知的FOO——但另一方面,我不知道它是否有效/聪明的typedef东西,FOO当库已经这样做。)
提前致谢!
我应该根据头文件和一些进一步的描述来制作一个程序。需要解决不透明类型的问题。不透明结构在头文件中与一些其他函数一起声明。但每个函数都应该有自己的 .c 文件,问题就来了。我应该做什么或者应该在哪里定义不透明结构以便我的函数可以使用它?
我有这样的文件:
header.h source.c(main) function1.c function2.c 等
在这种情况下我不知道该怎么办。
我正在 Xcode 中使用 Swift,但收到以下错误:--“类别”类型(又名“OpaquePointer”)的值没有成员“名称”--我到处找,但找不到解决方案。有人知道该怎么做吗?
谢谢你的帮助!