简体   繁体   中英

const Struct parameter in C

I'm studying simple binary tree. I saw a model answer and had a question. In this code Item and Tree are structs.

typedef struct {
    char characters[20];
    char name[20];
} Item;

typedef struct node {
    Item item;
    struct node* left;
    struct node* right;
} Node;

typedef struct tree {
    Node* root;
    int size;
} Tree;

And I'll show two function prototypes.

bool InTree(const Item* pi, const Tree* ptree);
Item* TreeSearch(Tree* ptree, const Item key);

One is using Item* and the other is using Item by parameter. I know what each means. But when const is used, I think there is no difference between these two. If we assumed the memory is big enough.

const Item* pi and const Item key which is better when used as a parameter for a function? Is it about coding style problem or is it intended?

/* 1 */ void foo(Item *pi)
/* 2 */ void foo(const Item *pi)
/* 3 */ void foo(const Item * const pi)

All three will pass the reference to the struct, not the struct itself. The difference is:

  1. the pointer pi and the referenced struct can be modified
  2. the pointer pi can be modified, the referenced struct cannot be modified
  3. the pointer pi and the referenced struct cannot be modified
/* 1 */ void foo(Item pi)
/* 2 */ void foo(const Item pi)

In both cases struct will be copied by value ie the whole struct will be passed to the function. If you modify the member it will not affect the original struct.

  1. struct pi can be modified
  2. struct pi cannot be modified

Between these two approaches of declarations of parameters with the specifier Item

bool InTree(const Item* pi, const Tree* ptree);
Item* TreeSearch(Tree* ptree, const Item key);

the approach with declaration the parameter like const Item* pi is more preferable compared with the declaration const Item key because in the second case the whole object of the structure type that contains character arrays is copied instead of coping only a pointer to the object that is more efficient.

const Item *pi means that *pi or *(pi + index) (or pi[index] ) cannot be modified.

const Item key means that key cannot be modified (after initialization in the case of a variable, or after assignment as part of the function call in the case of a function parameter).


bool InTree(const Item* pi, const Tree* ptree);

I guess that InTree searches whether the specific Item node pointed to by pi is present in the tree whose root node is pointed to by ptree . (Ie it is searching for a pointer to the specific Item rather than searching for a matching Item .) There is no need to modify any Item in the tree or the Item pointed to by pi , so both parameters can be of type const Item * to indicate that nothing will be modified by the function.


Item* TreeSearch(Tree* ptree, const Item key);

I guess that TreeSearch searches the tree whose root node is pointed to by ptree to find a node that matches Item key . I guess that only the "value" parts of the Item will be compared with nodes in the tree and the "linkage" parts of the Item will be ignored. I guess the function will return a pointer to the Item in the matching node in the tree if one is found, otherwise it will return a null pointer.

Declaring the parameter key as const Item key is a coding style issue. It makes no difference to the caller of the function because arguments are passed by value. It only makes a difference in the function definition, preventing the function body from modifying the value of the parameter.

I guess the parameter ptree could be declared as const Tree * assuming the function does not modify the *ptree .

I guess the function return type is Item * rather than const Item * because the caller of the function might want to modify the (indirectly) returned Item in some way.


As a side note, even if the TreeSearch function is defined as

Item* TreeSearch(Tree* ptree, const Item key)
{
    /* ... implementation omitted ... */
}

then it will match this declaration without the const qualifier

Item* TreeSearch(Tree* ptree, Item key);

so that const qualifier for parameter key really is superfluous in the declaration of the function, even if it is not superfluous in the definition of the function.

That does not apply to the declaration of the InTree function.


For Item* TreeSearch(Tree* ptree, const Item key); , if the type Item is considered "large", then it would be more practical to change the parameter key to const Item *key in order to reduce the function call overhead. The programmer should use their best judgement about that. The function would then be defined to find an Item node in the tree that matches *key (considering only the "value" parts of Item and ignoring the "linkage" parts), not to find the specific Item node pointed to by key .

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