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是一个双解引用。编辑:实际上我认为我同意马克,代码> > >代码>比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;
}