消除void **与any_struct_t **警告

时间:2015-10-12 08:21:40

标签: c pointers

如何在编译器检查以确保传递的参数是指向指针的指针时,如何正确消除此警告?

void somefunc (void **elements)
{
    // This function works on any array type
    // Maybe it prints pointer addresses
    void **pp;
    for (pp = elements; *pp; pp ++)
        printf ("address: %x\n", *pp);
}

int main (const char *cmdline)
{
    typedef struct {
        int a, b, c;
    } any_struct_t;

    any_struct_t *group[25] = {0}; // (any_struct_t **) 
    group[0] = malloc (sizeof(any_struct_t));
    somefunc(group); // <--- WARNING (any_struct_t **) vs. (void **)
    getchar ();
    exit (0);
}

是否有&#34; double void&#34; 类型的指针或一些超级模糊的C技巧,可以在这里正确使用它来正确摆脱此警告:

I want this warning to go away via code:
warning: passing argument 1 of 'somefunc' from incompatible pointer type 
expected 'void **' but argument is of type 'any_struct_t **'

该函数需要一个指向指针的指针,它并不关心它是什么类型的指针。

我可以通过强制转换为(void *)来消除警告,但编译器不再检查它是否是指向指针的指针。

3 个答案:

答案 0 :(得分:1)

void*是唯一的通用指针类型,每个其他指针类型都可以隐式转换为/。这不适用于void**,因为正式void**不需要与x**具有相同的实现。

但是,正如您所指出的,您只需转发到void*,警告就会消失。从理论上讲,这不是便携式的。在实践中,我非常怀疑你这样做会遇到任何问题。

因此,如果你顽固地担心类型安全,那么你不会只是转向void*并继续前进的唯一原因。如果你是,你应该编写一个函数来处理每个单独的指针类型。

例如,在C11中,您可以使用_Generic关键字优雅地执行此操作:

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


typedef struct {
    int a, b, c;
} any_struct_t;


#define some_func(ptr) \
_Generic( (ptr), \
          any_struct_t**: some_any_struct)(ptr)

void some_any_struct (any_struct_t** pp)
{
  for(; *pp != NULL; pp++)
  {
    printf ("address: %p\n", (void*)*pp);
  }
}


int main(void)
{
  any_struct_t* array [4] = {0};

  array[0] = malloc(10*sizeof(any_struct_t));
  array[1] = malloc( 1*sizeof(any_struct_t));
  array[2] = malloc( 5*sizeof(any_struct_t));
  array[3] = NULL;

  some_func(array);

  void* void_array[3];
  some_func(void_array);  // will cause compiler error, because void** is not supported
}

答案 1 :(得分:0)

如果传递的参数不是(至少)指向指针的指针,则至少会产生编译时错误。它并不完全是主意,但至少有类型检查。

void _somefunc (void **elements)
{
    // This function works on any array type
    // Maybe it prints pointer addresses
    void **pp;
    for (pp = elements; *pp; pp ++)
        printf ("address: %p\n", *pp);
}

// ENSURE AT LEAST A POINTER TO A POINTER IN DEBUG BUILDS, WILL CAUSE ERROR IF NOT.
// error: invalid type argument of unary '*'
#ifdef DEBUG
    // Ensure at least a pointer to a pointer.  Compile-time error if not.
    #define somefunc(x) _somefunc ((void **)x + sizeof(**x) - sizeof(**x)) 
#else
    #define somefunc(x) _somefunc (((void **)x) // No warnings in release
#endif

答案 2 :(得分:0)

$app->register(new Silex\Provider\DoctrineServiceProvider(), array(
    'dbs.options' => array (
        'mysql_read' => array(
            'driver'    => 'pdo_mysql',
            'host'      => 'mysql_read.someplace.tld',
            'dbname'    => 'my_database',
            'user'      => 'my_username',
            'password'  => 'my_password',
            'charset'   => 'utf8mb4',
        ),
        'mysql_write' => array(
            'driver'    => 'pdo_mysql',
            'host'      => 'mysql_write.someplace.tld',
            'dbname'    => 'my_database',
            'user'      => 'my_username',
            'password'  => 'my_password',
            'charset'   => 'utf8mb4',
        ),
    ),
));

}