Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/67.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 带typedef的指针类型错误_C_Pointers_Struct_Typedef - Fatal编程技术网

C 带typedef的指针类型错误

C 带typedef的指针类型错误,c,pointers,struct,typedef,C,Pointers,Struct,Typedef,当调用以字符串指针作为参数的函数时,我遇到了问题。我需要得到一个元素的名称 // method void getStringFromCsv( char ** str ); 让我介绍一下我正在使用的结构(不是我写的,也是一个更大项目的一部分,我不能修改它们) 所以,基本上,我想我会这样调用函数: T_Element * pData; // Not null, filled earlier getStringFromCsv( &pData->pElement->name );

当调用以字符串指针作为参数的函数时,我遇到了问题。我需要得到一个元素的名称

// method
void getStringFromCsv( char ** str );
让我介绍一下我正在使用的结构(不是我写的,也是一个更大项目的一部分,我不能修改它们)

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

T_Element * pData; // Not null, filled earlier
getStringFromCsv( &pData->pElement->name );
但这不起作用(警告:从不兼容的指针类型传递'STR_toCsv'的参数1)。我将gcc与NetBeans 6.8一起使用

我尝试了很多东西

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
…但最终将名称转换为字符**:

getStringFromCsv( (char**) &pData->pElement->name );
我的代码有什么问题? 基本上,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;
  }
}

是的,在封面下,T_符号的处理方式类似于字符*。但您已将其声明为char[64],因此您传入的是指向char[64]的指针,而不是指向char的指针。编译器正在为您跟踪这一点


就我个人而言,在这种情况下,我会像你在问题结束时所做的那样来表达

name
是一个字符数组,因此&name给您一个指向char[64]的指针,正如Vicky已经回答的那样。但是casting使事情变得更糟,因为它告诉编译器将数组的第一个字符作为指向实际数组的指针

请参阅C-FAQ:

我想您可以在这里使用临时字符*:

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

如果函数预期会出现这种情况。应为
字符**
,请确保它不会尝试重新分配内存。只需填充一个
字符*
就足够了。

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

void getStringFromCsv(T_SYMBOL * str);
或者,您可以使用安全提供的临时
char*
,但这样做没有多大意义,因为无法使用对该
char*
值的任何更新-
->name
成员不能修改,因为它是一个数组

您不妨将函数声明为:

void getStringFromCsv( char * str );
…并称之为:

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


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

getStringFromCsv( &(char *){ pData->pElement->name } );
考虑到这一点:

不是一回事(即使它们看起来是)。 所以我的符号和字符*不能交换,对吗


有解决方法吗?或者其他解决方案吗?

唉,人们没有告诉你的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;
}
#包括
int main(int argc,const char*argv[]
{
charx[5];
char*y;
printf(“%08x\n”,x);
printf(“%08x\n”、&x);
printf(“%08x\n”,y);
printf(“%08x\n”、&y);
返回0;
}

我不作为答案发布,因为我需要检查我所说的内容。但基本上,SYMBOL=const char*,而不是char*。所以SYMBOL*=const char**与char**不兼容。您是否尝试过
&(pData->pElement->name)
?调用不应该是getStringFromCsv(pData->pElement->name)吗?因为pData已经是一个指针&pData是一个双解引用。编辑:实际上我认为我同意马克,代码> > >代码>比和 >更高的优先级。@ PMOD:不,这是C,不是C++。强制转换不会有帮助,因为当您尝试取消引用通过取消引用强制转换值而获得的无意义
char*
值时,它将崩溃。无论如何,感谢您的解释。很遗憾,修改函数原型不是一个选项。Thanks@Isaac克拉克:在这种情况下,您需要编辑您的问题以显示
getStringFromCsv()
函数的源代码,或者至少显示其文档化的接口.Done;)(很抱歉延迟,我想我们不在同一时区)@Isaac Clarke:由于函数只读取
*数据,而不改变它,因此临时
char*
解决方案是正确的(但正如您所看到的,没有任何实际的理由说明函数不能首先使用
data
来代替
*data
!)主开发人员自己告诉我这是他的一个错误。更改此选项将意味着大规模重构,因此也不是一个真正的选项。我将使用temp char,谢谢。谢谢!我不喜欢临时变量的想法,不过…转换是否更糟?转换实际上会导致未定义的行为,并且很可能会导致我n崩溃。正如我所说,仔细阅读
getStringFromCsv
的文档,因为通常会有一个原因来解释为什么会使用一个级别的间接寻址。如果您提供此文档,那么我们可以建议具体的解决方法,但在不知道的情况下,我们只能猜测。我也不喜欢使用临时变量。但是,这个解决方案是我能想到的唯一安全的方法。理想的方法是更改函数原型,但您提到这不是一个选项。正如安全提到的,函数最好不要试图修改
str
本身,否则可能会遇到大问题。临时变量有什么问题?Functio堆栈上的n个局部变量很便宜,如果我不得不多次使用
pData->pElement->name
,那么为了方便和可读性,我会将其存储在一个变量中。当然,不调用它
tmp
。当然,这表明两个设计不匹配,需要一些粘合代码。我编辑了第一个发帖向您展示getStringFromCsv//我主要关心的是创建变量的可重用性。我的代码将在外部使用,而不仅仅是主要开发人员使用。我希望用户能够编码,只知道标题。强制转换将是“逻辑的”。谢谢
char  a[4] = "hello";
char* p = "hello";
#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;
}