开发者

Bad pointer type with a typedef

开发者 https://www.devze.com 2023-01-04 22:29 出处:网络
I\'m having troubles when calling a function taking a pointer to a string as a parameter. I need to get an Element\'s name.

I'm having troubles when calling a function taking a pointer to a string as a parameter. I need to get an Element's name.

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

Let me introduce the structures I'm working with (not written by me and part of a much bigger project, I can't modify them).

// 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;

So, basically, I thought I would call the function like this :

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

But this doesn't work (warning: passing argument 1 of ‘STR_toCsv’ from incompatible poi开发者_StackOverflow中文版nter type). I'm using gcc with NetBeans 6.8.

I tried many things...

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

...but ended up casting name to a char ** :

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

What is wrong with my code ? Basically, SYMBOL = CHAR *, right ? Why is SYMBOL* != CHAR** ? I'm pretty sure I'm missing something simple but right now... Nothing came.

EDIT Here is 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;
  }
}


If you wish to pass &pData->pElement->name to the function, the function must be declared as:

void getStringFromCsv(T_SYMBOL * str);

Alternatively you can use a temporary char * as Secure offered - but there's not much point in doing this, because any updates to that char *'s value can't be used - the ->name member can't be modified, as it's an array.

You might as well just declare the function as:

void getStringFromCsv( char * str );

...and call it as:

getStringFromCsv( pData->pElement->name );

(In this case, the function can still change the contents of the ->name array. What you can't do is to change the position of the array itself).


As well as Secure's option, there's another way if your compiler supports C99 compound literals:

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


name is an array of chars, so &name gives you a pointer to char[64], as Vicky already answered. But casting makes things worse, because it tells the compiler to treat the first chars of the array as a pointer to the real array.

See the C-FAQ: http://c-faq.com/aryptr/aryptr2.html

I think you can use a temporary char* here:

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

If this is expected by the function. Expecting a char**, make sure that it doesn't try to reallocate the memory. For simply filling it, a char* would be enough.


Alas, one of the little secrets of C that people fail to tell you, an array is not the same thing as a pointer. if x is defined as int x[5] or whatever, &x == x. Try out this code below:

#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;
}


Considering this : http://c-faq.com/decl/strlitinit.html

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

Aren't the same thing (even if they seem to be). So my SYMBOL and CHAR* cannot be exchanged, right ?

Is there a workaround, or another solution ?


Yes, under the covers T_SYMBOL is handled like a char *. But you've declared it as a char[64], so you're passing in a pointer to a char[64] not a pointer to a pointer to a char. The compiler is keeping track of that for you.

Personally in this situation I would just cast it as you did at the end of your question.

0

精彩评论

暂无评论...
验证码 换一张
取 消