c - 如何在 C 中的 void * 中存储 double

标签 c pointers void

我找到了Converting double to void* in C但我无法运行任何解决方案。我想创建一个带有 void 指针的结构来存储不同类型的数据。

struct Table {
    int id;
    void *val;
}; 

在主函数中,我分配如下值

struct Table t;

int i = 1;
double d = 2.5;

double *pd = &d;
void **p = (void**)pd;
void *dp = *p;

t.id = i;
t.val = dp;

但我无法获得 double 值..

printf("%d %f", t.id, t.val);

谢谢。

最佳答案

几点:

  1. 您不需要中介pd分配地址dt.val 。以下内容应该可以完美运行:
    t.val = &d;
    C 允许在 void * 之间直接赋值和其他指针类型。 C++ 没有,所以如果没有强制转换,这在 C++ 中不起作用:
    t.val = (void *) &d;
  2. 但是,这假设您将使用 t.vald 的一生中。如果有机会d在使用 t.val 之前将超出范围,那么你应该分配一个新的内存块来存储 d 的值:
    t.val = malloc( sizeof d );
    if ( t.val )
      *(double *)t.val = d;
    
    因此,不要存储 d 的地址在t.val ,您正在存储动态分配的内存块的地址,并复制 d 的值到那个动态 block 。自 t.val是指向 void 的指针,首先需要使用强制转换表达式 (double *)告诉编译器将其视为指向 double 的指针。然后您需要使用一元 * 取消引用该指针运算符来分配 d 的值到那个新的内存块。这也意味着您在使用完该 block 后需要取消分配该 block :
    free( t.val );
  3. 无论哪种方式,您都会打印 t.val 的值。指向如下:
    printf( "%d %f\n", t.id, *(double *)t.val );
    同样,我们必须告诉编译器处理 t.val作为指向 double 的指针并使用一元 *运算符来获取指针指向的值。

编辑

这是一个非常人为的例子来说明我对 d 的意思。 “超出范围”。假设我们创建 t main 中的对象,然后调用一个分配 t.val 的函数在该函数中使用局部变量,然后调用另一个函数来打印 t.val 的值指向:

/**
 * Sets the val member of a struct Table object. Since we want to 
 * modify the contents of the parameter, we need to pass a pointer
 * to it.
 */
void assignVal( struct Table *tbl ) 
{
  double d = some_value();        // d only exists for the duration of this function
  ...
  tbl->val = malloc( sizeof d );  // since tbl is a pointer, use ->
  if ( tbl->val )                 // instead of . to access members
    *(double *) tbl->val = d;
  else
    // error could not allocate memory for tbl->val
  ...
}

void printVal( struct Table tbl )
{
  ...
  if ( tbl.val )
    printf( "%d %f\n", tbl->id, *(double *) tbl.val );
  else
    // tbl.val was never allocated
  ...
}

int main( void )
{
  struct Table t;
  assignVal( &t );
  printVal( t );
  if ( t.val )
    free( t.val );
}

因为我们想要assignVal修改 t 的内容,我们需要将一个指针作为参数传递给它。语法tbl->val(*tbl).val 相同- 我们取消引用 tbl在尝试访问 val 之前成员。

d一旦 assignVal 就不复存在退出后,我们需要分配一个新的对象来存储d的值。一旦我们完成了该值,我们就释放 t.val .

在此示例中,assignValprintVal两者都假设 t.val指向double目的。对于更通用的代码,您可能需要添加另一个成员来跟踪对象 val 的类型。指向。

例如:

struct Table {
  int id;
  int valueType;
  void *val;
};

void assignDblVal( struct Table *tbl )
{
  double d = ...;
  ...
  t->valueType = DOUBLE; // where DOUBLE is some kind of integer constant
  t->val = malloc( sizeof d );
  if ( t->val )
    *(double *) t->val = d;
  ...
}

void assignIntVal( struct Table *tbl )
{
  int x = ...;
  ...
  tbl->valueType = INT;
  tbl->val = malloc( sizeof x );
  if ( tbl->val )
    *(int *) tbl->val = x;
  ...
}

void printVal( struct Table tbl )
{
  switch( tbl.valueType )
  {
    case CHAR:
      printf( "%d '%c'\n", tbl.id, *(char *) tbl.val );
      break;

    case INT:
      printf( "%d %d\n", tbl.id, *(int *) tbl.val );
      break;

    ...

    case DOUBLE:
      printf( "%d %f\n", tbl.id, *(double *) tbl.val );
      break;

    ...
  }
}

这边,printVal不必假设 tbl.val指向 double - 我们告诉它它指向什么类型,然后它使用正确的转换和格式说明符来进行打印。

请记住,这些都是简单的例子。在 C 中,有很多更聪明的方法来处理类型多态性。我现在想不出一种方法。

关于c - 如何在 C 中的 void * 中存储 double ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54635806/

相关文章:

c - 使用循环将 Char 值添加到链接列表 [C]

C++函数声明

ios - Return 函数内部为 Void

c - 使用位操作的浮点乘法

c - 使用PACKET_MMAP和PACKET_TX_RING发送数据比 “normal”慢(无)

使用cmake对树莓派进行C交叉编译找不到头文件

我可以制作一个从某个指针开始并在它开始的地方结束的循环吗?

c - C 中函数指针如何工作

c - SSL_CTX_new 中的段错误

java - 我不知道这个 void 方法是如何工作的