类型化(或deference)void *到struct foo *

时间:2012-04-17 00:27:34

标签: c casting void-pointers

在api.h中

typedef void* hidden_my_type;
void do_something(my_type x);

在core.c中

struct _my_type
{
    int a;
}

void do_something(hidden_my_type void_x)
{
   struct *_my_type x = void_x;  /*Don't understand is that correct way to do, as I'm getting segmentation fault error */
   printf("Value: %d\n", x->a);
}

我想的其他方式,

struct *_my_type x = (struct _my_type *)malloc(sizeof(struct _my_type));
void_x = x
printf(Value: %d\n", x->a);

但我仍然遇到seg-fault错误。


好的,这是void * ....

的问题

e.g。 在core.c中

void init_my_type(hidden_my_type a)
{
   my_type *the_a = malloc(...);
   a = the_a   // <<<<<<<<<<<<<<<<<<<<<<<<<<<< is this correct?! a is void* and the_a // is original type
   pthread_cond_init(&the_a->...);
    .. (in short any other methods for init ..)
}
void my_type_destroy(my_hidden_type x)
{
    my_type *the_x = x;
    pthread_detroy(&the_x-> ...);
}

在main.c中

test()
{
   my_hidden_type x;
   init_my_type(x);
   .... 
   my_type_detroy(x);
}

这自我应该失败。在main.c测试函数中,x是void * ... init将分配但在destroy中我再次传递void * ..这可以是任何东西!

编辑(为我解决)

在api.h中

typedef void* hidden_my_type;
void do_something(my_type x);

在core.c中

 struct _my_type
    {
        int a;
    }


 void init_hidden_type(hidden_my_type void_p_my_type)
    {
        struct _my_type *real_my_type = (struct _my_type *)malloc(sizeof(struct _my_type));
        //--- Do init for your type ---
        void_p_my_type = real_my_type;
    }


 void do_something(hidden_my_type void_x)
    {
       struct *_my_type x = void_x; 
       printf("Value: %d\n", x->a);
    }

2 个答案:

答案 0 :(得分:1)

版本0 - 对问题代码的批判

发布的代码无法编译。

api.h

typedef void* hidden_my_type;
void do_something(my_type x);

这定义了hidden_my_type,但没有定义传递给my_type的{​​{1}}。据推测,你打算:

do_something()

core.c

typedef void *my_type;
void do_something(my_type x);

如下所述,结构定义后缺少分号。

struct _my_type
{
    int a;
}

您再次遇到void do_something(hidden_my_type void_x) { struct *_my_type x = void_x; printf("Value: %d\n", x->a); } vs hidden_my_type问题。你有指针的my_type,它不能去;它必须在*之后。你可能想要这样的东西:

struct _my_type

这在语法上是正确的(我认为;我实际上并没有通过编译器运行它)。你还没有说明它是如何使用的;实际上,由于用户代码无法生成指向有效结构的指针,因此无法安全地使用此代码。

您的测试代码(未显示 - 为什么不显示您的测试代码)可能如下所示:

void do_something(my_type void_x)
{
   struct _my_type *x = void_x;
   printf("Value: %d\n", x->a);
}

或者,它可能没有#include "api.h" int main(void) { my_type x = 0; do_something(x); return 0; } 初始值设定项。无论哪种方式,您的代码都无法正常运行,核心转储几乎是不可避免的。当您从用户隐藏结构时,您必须为它们提供一种机制来获取结构的有效(指针),并且您没有这样做。

版本1

这是一种更好的方法,因为它更接近于类型安全:

api.h版本1

= 0

core.c版本1

typedef struct _my_type *my_type;
void do_something(my_type x);

请注意添加的分号和#include "api.h" struct _my_type { int a; }; 文件的包含。

api.h

第2版

实际上,我们可以辩论隐藏指针的智慧;我宁愿不这样做:

api.h版本2

void do_something(my_type x)
{
    // Now you don't have to do casting here!
    //struct *_my_type x = void_x;  /*Don't understand is that correct way to do, as I'm getting segmentation fault error */
    printf("Value: %d\n", x->a);
}

core.c版本2

#ifndef API_H_INCLUDED
#define API_H_INCLUDED

typedef struct my_type my_type;
extern void     do_something(my_type *x);
extern my_type *my_type_initializer(void);
extern void     my_type_release(my_type *x);

#endif /* API_H_INCLUDED */

的main.c

#include "api.h"
#include <stdio.h>
#include <stdlib.h>

struct my_type
{
    int a;
};

void do_something(my_type *x)
{
    printf("Value: %d\n", x->a);
}

my_type *my_type_initializer(void)
{
    my_type *x = malloc(sizeof(*x));
    x->a = 57;  // More plausibly, this would be 0
    return x;
}

void my_type_release(my_type *x)
{
    free(x);
}

那很干净。当然,用户不能分配#include "api.h" int main(void) { my_type *x = my_type_initializer(); do_something(x); my_type_release(x); return 0; } (仅指向它的指针),因此您需要一个函数来为它们分配结构。考虑标准C库,struct my_type类型和FILE分配和fopen()发布和fclose()等来操纵类型。 fprintf()my_type_initializer()类似,fopen()my_type_release()类似,fclose()do_something()类似。< / p>

答案 1 :(得分:0)

乔纳森,你打败了我的答案,但这也许有帮助。这里,api.c包含(私有)实现,api.h提供其他代码(如main.c)使用的接口。

// main.c: uses only the public interface to the private code
#include "api.h"

int main(int argc, char *argv[]) {
  void *foo;

  foo = create_foo("five", 5);
  print_foo(foo);
  delete_foo(foo);
}
// EOF main.c


// api.h: the public interface
#ifndef _api_h_
#define _api_h_
void *create_foo(char *name, int number);
void print_foo(void *foo);
void delete_foo(void *foo);
#endif // _api_h_


// api.c: the private implementation
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// The real structure is private to the implementation.
typedef struct {
        char name[20];
        int number;
} real_struct;

// Create a new structure, initialize, return as ptr-to-void.
void *create_foo(char *name, int number) {
  real_struct *s = malloc(sizeof(real_struct));
  strcpy(s->name, name);
  s->number = number;
  return (void *) s;
}

// Print the data.
void print_foo(void *foo) {
  real_struct *s = (real_struct *) foo;
  printf("name: %s, number: %d\n", s->name, s->number);
}

// Release the memory.
void delete_foo(void *foo) {
  free(foo);
}
// EOF api.c

此代码应编译并运行:

$ gcc -o foo main.c api.c
$ ./foo

name: five, number: 5