const C 中的结构参数

const Struct parameter in C

提问人:SungJin Park 提问时间:2/5/2022 最后编辑:Vlad from MoscowSungJin Park 更新时间:2/5/2022 访问量:934

问:

我正在研究简单的二叉树。 我看到了一个模型答案,并有一个问题。 在此代码中,并且是结构体。ItemTree

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;

我将展示两个函数原型。

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

一个是使用 Item*,另一个是使用 Item by parameter。我知道每个意味着什么。但是当使用时,我认为这两者之间没有区别。如果我们假设内存足够大。const

const Item* pi当用作函数的参数时,哪个更好? 是关于编码风格问题还是有意为之?const Item key

C 结构 参数 传递引用

评论

0赞 Ed Heal 2/5/2022
请发布 - 否则我们将不得不再次猜测structs
0赞 Jules 2/5/2022
你能详细说明你的问题吗,我看不出问题所在。你是在问为什么要用吗?const
0赞 hyde 2/5/2022
所以,澄清一下,你假设会作为地址传递,而实际值不在堆栈中,因为 Item 太大了?然后可以作为地址传递给“原始”变量,因为 const,避免任何复制,因此在引擎盖下与将指针传递给 const 没有什么不同?我理解正确吗?Item keyconst Item key

答:

2赞 0___________ 2/5/2022 #1
/* 1 */ void foo(Item *pi)
/* 2 */ void foo(const Item *pi)
/* 3 */ void foo(const Item * const pi)

这三者都会将引用传递给结构,而不是结构本身。区别在于:

  1. 可以修改指针和引用的结构pi
  2. 指针可以修改,引用的结构不能修改pi
  3. 无法修改指针和引用的结构pi
/* 1 */ void foo(Item pi)
/* 2 */ void foo(const Item pi)

在这两种情况下,struct 都将按值复制,即整个结构将被传递给函数。如果修改成员,则不会影响原始结构。

  1. 结构可以修改pi
  2. 结构体无法修改pi

评论

1赞 Barmar 2/5/2022
我认为他希望当你使用它时会优化副本并只会传递一个指针。这是“好像”规则允许的。const Item pi
0赞 0___________ 2/5/2022
@Barmar 我希望我明确表示它不会以这种方式优化它
1赞 Vlad from Moscow 2/5/2022 #2

在这两种使用说明符声明参数的方法之间Item

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

与声明相比,声明参数 like 的方法更可取,因为在第二种情况下,复制包含字符数组的结构类型的整个对象,而不是只处理指向更有效的对象的指针。const Item* piconst Item key

1赞 Ian Abbott 2/5/2022 #3

const Item *pi表示 or (或 ) 无法修改。*pi*(pi + index)pi[index]

const Item key表示无法修改(在变量的情况下在初始化后,或者在函数参数的情况下作为函数调用的一部分进行赋值后)。key


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

我猜会搜索指向 的特定节点是否存在于根节点指向 的树中。(即,它正在搜索指向特定事物的指针,而不是搜索匹配项。无需修改树中的 any 或指向的 by ,因此这两个参数都可以是 type 来指示函数不会修改任何内容。InTreeItempiptreeItemItemItemItempiconst Item *


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

我猜会搜索根节点指向的树以找到与 匹配的节点。我猜只有 的“值”部分会与树中的节点进行比较,而 的“链接”部分将被忽略。我猜如果找到一个,该函数将返回指向树中匹配节点的指针,否则它将返回一个空指针。TreeSearchptreeItem keyItemItemItem

将参数声明为是编码样式问题。它对函数的调用者没有区别,因为参数是按值传递的。它只会在函数定义中产生影响,防止函数体修改参数的值。keyconst Item key

我想该参数可以声明为假设该函数不修改 .ptreeconst Tree **ptree

我猜函数返回类型不是因为函数的调用者可能想要以某种方式修改(间接)返回的。Item *const Item *Item


顺便说一句,即使函数定义为TreeSearch

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

然后它将匹配此声明,而不带限定符const

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

因此,参数的限定符在函数的声明中确实是多余的,即使它在函数的定义中不是多余的。constkey

这不适用于函数的声明。InTree


对于 ,如果类型被认为是“大”的,那么将参数更改为 以减少函数调用开销会更实用。程序员应该对此做出最佳判断。然后,该函数将被定义为在树中查找匹配的节点(仅考虑 的“值”部分并忽略 “链接”部分),而不是查找 指向的特定节点。Item* TreeSearch(Tree* ptree, const Item key);Itemkeyconst Item *keyItem*keyItemItemkey