Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/59.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 如何禁用对不透明变量的整数赋值(0)?_C_Opaque Pointers - Fatal编程技术网

C 如何禁用对不透明变量的整数赋值(0)?

C 如何禁用对不透明变量的整数赋值(0)?,c,opaque-pointers,C,Opaque Pointers,我有一个模块,我想对它的客户机隐藏它的实现 我选择声明一个不透明类型,它实际上是指向只在实现中定义的结构的指针 这一切都很好,只是我可以将零值赋给这种类型的变量,这是我想要避免的 这里有一个C语言的例子 头文件foo.h /* foo.h */ typedef struct foo *foo_t; /* <- sorry this was obviously flawed, the '*' was missing */ extern void foo_create( foo_t *t

我有一个模块,我想对它的客户机隐藏它的实现

我选择声明一个不透明类型,它实际上是指向只在实现中定义的结构的指针

这一切都很好,只是我可以将零值赋给这种类型的变量,这是我想要避免的

这里有一个C语言的例子

头文件foo.h

/* foo.h */
typedef struct foo *foo_t; /* <- sorry this was obviously flawed, the '*' was missing */


extern void foo_create( foo_t *t );
extern void foo_destroy( foo_t *t );
extern void foo_tile( foo_t x );
/*foo.h*/
typedef结构foo*foo\u t;/*一些_成员++;
}
下面是一个使用该模块的示例客户端: B.c:

#包括“foo.h”
int main(int argc,字符**argv)
{
富托;
foo_创建(&toe);

toe=0;/*首先,您的typedef是错误的:
typedef struct foo foo\u t;
(因此它是您的
main
,否则编译器将捕获结构的赋值)

对于不透明类型,通常会执行如下操作:
typedef struct foo*foo\t;
。否则您的
脚趾将不会是您发布的示例中的指针(这就是为什么您必须使用&)传递它。考虑到
foo\u create
中的
malloc
,我很确定您键入了错误的typedef

第二,问问你自己,你打算如何使用清理功能(
foo\u destroy
)释放内存,对吗?用户应该把这个指针传递给清理功能。

这样考虑:如果用户没有足够的空间给它分配一个整数,<强>为什么她没有足够的内存来忘记清理< /强>? 编辑 Stéphane Gimenez评论道typedef struct foo foo_t是OP想要的。我想强调一下:

客户机可以对这种类型的对象执行的唯一操作是 获取其地址,生成不透明指针


首先,您的typedef是错误的:
typedef struct foo foo\u t;
(因此它是您的
main
,否则编译器将捕获结构的赋值)

对于不透明类型,通常会执行如下操作:
typedef struct foo*foo\t;
。否则您的
脚趾将不会是您发布的示例中的指针(这就是为什么您必须使用&)传递它。考虑到
foo\u create
中的
malloc
,我很确定您键入了错误的typedef

第二,问问你自己,你打算如何使用清理功能(
foo\u destroy
)释放内存,对吗?用户应该把这个指针传递给清理功能。

这样考虑:如果用户没有足够的空间给它分配一个整数,<强>为什么她没有足够的内存来忘记清理< /强>? 编辑 Stéphane Gimenez评论道typedef struct foo foo_t是OP想要的。我想强调一下:

客户机可以对这种类型的对象执行的唯一操作是 获取其地址,生成不透明指针


您的想法是错误的。如何启动本地foo\u t变量?如果键入

void bar(void)
{
  foo_t var;
}
然后var将包含垃圾。使其干净的唯一方法是键入

void bar(void)
{
  foo_t var = NULL;
}
或者
0
如果您愿意,但这应该会发出警告。因此,您问题中的代码不安全,可能会崩溃

您可以做的是将nonnull属性添加到foo_tile,即:

void foo_tile( foo_t t ) __attribute__((nonnull(1)));
这将防止
foo_tile(NULL);
甚至在某些编译器中

foo_t var = NULL;
foo_tile(var);

虽然这可能只是一个警告,而不是一个严重错误。

您的想法是错误的。您将如何启动本地foo\t变量?如果您键入

void bar(void)
{
  foo_t var;
}
然后var将包含垃圾。使其干净的唯一方法是键入

void bar(void)
{
  foo_t var = NULL;
}
或者
0
如果您愿意,但这应该会发出警告。因此,您问题中的代码不安全,可能会崩溃

您可以做的是将nonnull属性添加到foo_tile,即:

void foo_tile( foo_t t ) __attribute__((nonnull(1)));
这将防止
foo_tile(NULL);
甚至在某些编译器中

foo_t var = NULL;
foo_tile(var);

虽然它可能只是一个警告,而不是一个硬错误。

我不确定您是否可以这样做。编译器将在main()中失败:

您可以尝试直接从foo_create()返回分配的内存,而不是传入foo_t参数(模拟构造函数):


我不确定您是否可以这样做。编译器将在main()中失败:

您可以尝试直接从foo_create()返回分配的内存,而不是传入foo_t参数(模拟构造函数):


C++或C?它们不一样,你可能只需要选择一个。0也是唯一可以隐式转换为任何指针类型的整数。如果代码< > FooStut真的是指针,你不能停止。这就像试图阻止<代码> 5 <代码>被分配到<代码> int >代码>。而且没有多少努力能改变它。我也怀疑THI。s实际上是代码的外观,因为您
typedef struct foo foo\u t;
但是
foo\u t toe;
toe=0;
。这是不可能的,因为您无法将
0
分配给结构。您可以使用数组类型使您的类型不可分配(因为数组在C中不是左值)但是,为了做到这一点,你必须提供完全的结构定义,这就破坏了不透明的类型。C++或C的目的,它们不一样,你可能只需要选择一个。0也是唯一可以隐式转换为任何指针类型的整数。如果代码> FooStutt真的是指针,你就不能停止。它是LIK。e试图阻止
5
被分配给
int
。这是任何努力都无法改变的。我也怀疑这是代码的真实外观,因为您
typedef struct foo foo foo_t;
但是
foo_t toe;
toe=0;
。这是不可能的,因为您无法将
0
分配给s您可以使用数组类型使您的类型不可分配(因为数组是
extern foo_t * foo_create( void );

foo_t * foo_create( void )
{
    foo_t * t;

    t = malloc( sizeof(struct foo) );  

    return(t);       
}

int main( int argc , char **argv )
{
    foo_t * toe;

    toe = foo_create();

    toe = 0; /* Clearly a memory leak via reassignment */
    ...
}