简体   繁体   中英

Return value types doesn't match in C

I have these 2 structs:

#define M 100
#define N 100

typedef struct xml_Element {
pData_Element           data;
pAttr_Element           attr_arr[M];
struct xml_Element      *parent;
struct xml_Element      *children[N];
int                     depth;
int                     num_of_children;
int                     num_of_attr;
} Xml_Element,*pXml_Element;

  typedef struct attrElem {
      char *attrName;
      char *attrValue;
   }Attr_Element,*pAttr_Element;

and I wrote this function:

pAttr_Element getXmlAttrArray(pXml_Element node) {
    return node->attr_arr;
}

I have a couple of questions:

  1. Why is it illegal? If I change the function to: {pAttr_Element* getXmlAttr....} it works but I don't understand why.

Inside my struct I have a pointer to an array, where every cell is a pointer of type pAttr_Element right? Or it's not a pointer to an array? I'm lost :(

  1. Why is it not working if I change the function to: Attr_Element getXmlAttrArray(..) ? When I return: node->attr_arr what is the return type?

  2. How can I change the struct in order to return a pointer to an array Of pAttr_elements?

Thank you!

The attr_arr field is an array of pAttr_Element , not a pAttr_Element . So you can't return it as pAttr_Element .
In C, arrays are not pointers, but they decay to pointers in many cases. When you write return node->attr_arr , the array decays to a pointer, which is then returned.

The xml_Element structure doesn't contain a pointer to the array of pAttr_Element . It actually contains 100 such structures.

Some thoughts on coding style :

This is a common misunderstanding with the meaning of typedef . People use it as if they are using macro definition.

Its very important to understand that typedef is storage class classifier . Its not a convenient name for what can be achieved by macro definitions. The real power of typedef pays off when you can create a really complicated type with a simple name to refer it to.

Example :

typedef void (*ptr_to_fun)(char *p)

This statement says that a pointer to a function taking pointer to char as argument and returning nothing can be called from now ptr_to_fun

So i can have statements like

ptr_to_fun ptr = my_fun

But its a little shame that majority of the cases, typedef is used to hide the struct keyword. Which is in my opinion a bad practice, because it accomplishes little but confuses a new c programmers. (Its may be because of overwhelming Object oriented crowd which whines about syntax over semantics more.) C can be Object oriented easily. Look at the linux kernel code. It has multiple inheritance and stuff. they didn't need to hide struct keyword. typedef is not meant to be for hiding struct keyword. It has a greater and important application.

Your code is...

#define M 100
#define N 100

typedef struct xml_Element {
pData_Element           data;
pAttr_Element           attr_arr[M];
struct xml_Element      *parent;
struct xml_Element      *children[N];
int                     depth;
int                     num_of_children;
int                     num_of_attr;
} Xml_Element,*pXml_Element;

so it says that xml_Element is a new type which is actually struct xml_Element . Also pxml_Element is a new type which is actually of type struct xml_Element * .

Now lets come to your problem.

your function is

pAttr_Element getXmlAttrArray(pXml_Element node) {
    return node->attr_arr;
}

So it will return pAttr_Element type. You have typedef ed it. So it actually stands for of type struct attrElem * .

Now your initial structure has pAttr_Element array. So what you are trying to do is to return an array. you can't return this. you can return a pointer to this array. Now your array is of type struct attr_Elem *pAttr_Elem[M] . its a array of pointers to struct attr_elem . So the return type which will be compatible with a pointer to this array will be like 'struct attr_Elem **pAttr_Elem[M] . after typedef it will be like 'pAttr_Element * . after typedef it will be like 'pAttr_Element *

And is not possible in c to return an array. Although the array may contain pointers(like in your case). But that does not matter. you can't return an array.

Think about why c does not permit this.

a function can return stuff in two ways. It can use registers designated for holding return values. Its also possible to manipulate the frame pointer and push stuff in stack which will be accessible after its frame has been gone to oblivion(not a standard practice though).

in x86_64 architecture you have 8 byte wide register which can hold a native pointer variable. So that's it. If you want to return a array, you have to return copy of large piece of memory. Which can't be done efficiently by the machine. But if you just return a pointer to it, then you can read off the returned pointer from the caller easily.

last word of wisdom, arrays are arrays, pointers are pointers. In some context they are interchangeable, but its a mistake to think they are the same without considering the context.

pAttr_Element is a pointer to Attr_Element.

In C, an array is a pointer.

attr_arr is an array of pAttr_Element, which means it's a pointer to a bunch of pAttr_Elements, or in other words, it's a pointer to a pointer of Attr_Element.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM