带有typedef的错误指针类型

时间:2010-06-29 12:08:31

标签: c pointers struct typedef

在调用函数时,我遇到了麻烦,它将指向字符串的指针作为参数。我需要获得一个Element的名字。

// method
void getStringFromCsv( char ** str );

让我介绍一下我正在使用的结构(不是由我编写的,而是一个更大的项目的一部分,我无法修改它们)。

// typedefs
typedef char      T_CHAR64[64];
typedef T_CHAR64  T_SYMBOL;

// generic element
typedef struct Element
{
  T_SYMBOL  name; 
} T_Element;

// csv element
typedef struct CsvElement
{
  Element * pElement;
  int   id;
} T_csvElement;

所以,基本上,我以为我会这样调用这个函数:

T_Element * pData; // Not null, filled earlier
getStringFromCsv( &pData->pElement->name );

但这不起作用(警告:从不兼容的指针类型传递'STR_toCsv'的参数1)。我在NetBeans 6.8中使用gcc。

我做了很多事......

T_SYMBOL foo = "foo";
T_SYMBOL * pFoo = &foo;

getStringFromCsv( pDef->name, &pFoo ); // error : passing from incompatible pointer type

T_CHAR * pBar = &foo;      // error : init from incompatible pointer type
T_CHAR * pBaz = &(foo[0]); // OK

getStringFromCsv( pDef->name, &pBaz ); // OK

T_SYMBOL * pFooTest = &(foo[0]); // error : init from incompatible pointer type

...但最终将名字命名为char **:

getStringFromCsv( (char**) &pData->pElement->name );

我的代码出了什么问题? 基本上,SYMBOL = CHAR *,对吧?为什么SYMBOL *!= CHAR **? 我很确定我错过了一些简单的东西但是现在......什么都没有来。

修改 这是getStringFromCsv:

void getStringFromCsv( char ** data )
{
  // pDesc is defined and not null
  csvDescriptorCat( pDesc, *data);
  csvDescriptorCat( pDesc, "\t");
}

void csvDescriptorCat( CsvDescriptor * pDesc, char* str)
{
  int len;
  if( str != NULL)
  {
    len = strlen(str);
    strcpy( &pDesc->line[pDesc->pos], str);
    pDesc->pos += len;
  }
}

5 个答案:

答案 0 :(得分:2)

name是一个字符数组,所以& name给你一个指向char [64]的指针,因为Vicky已经回答了。但是渲染使事情变得更糟,因为它告诉编译器将数组的第一个字符视为指向真实数组的指针。

请参阅C-FAQ:http://c-faq.com/aryptr/aryptr2.html

我认为你可以在这里使用临时char *:

char *tmp = pData->pElement->name; // array decays to pointer
getStringFromCsv(&tmp);

如果函数需要这个。期待char**,确保它不会尝试重新分配内存。只需填写char*即可。

答案 1 :(得分:2)

如果您希望将&pData->pElement->name传递给函数,则必须将该函数声明为:

void getStringFromCsv(T_SYMBOL * str);

或者你可以使用临时char *作为安全提供 - 但这样做没有多大意义,因为无法使用char *值的任何更新 - {{1无法修改成员,因为它是一个数组。

您也可以将该函数声明为:

->name

...并将其命名为:

void getStringFromCsv( char * str );

(在这种情况下,该函数仍然可以更改getStringFromCsv( pData->pElement->name ); 数组的内容。你不能做的是改变数组本身的位置。)


除了Secure的选项之外,如果您的编译器支持C99复合文字,还有另一种方法:

->name

答案 2 :(得分:1)

唉,人们没有告诉你的C的一个小秘密,一个数组与指针不同。如果x被定义为int x [5]或其他什么,& x == x。请尝试以下代码:

#include <stdio.h>
int main(int argc, const char *argv[])
{
   char x [5];
   char *y;

   printf("%08x\n", x);
   printf("%08x\n", &x);
   printf("%08x\n", y);
   printf("%08x\n", &y);

   return 0;
}

答案 3 :(得分:0)

考虑到这一点:http://c-faq.com/decl/strlitinit.html

char  a[4] = "hello";
char* p = "hello";

不一样(即使它们似乎是)。 所以我的SYMBOL和CHAR *无法兑换,对吧?

是否有解决方法或其他解决方案?

答案 4 :(得分:-2)

是的,在封面T_SYMBOL处理就像char *。但是你已经将它声明为char [64],所以你传入一个指向char [64]的指针,而不是指向char的指针。编译器正在为您跟踪。

就这种情况而言,我会像你在问题结束时那样投出它。