rec*_*ecp 0 c function c99 c89 function-parameter
在函数内部重新分配函数参数是不好还是好的做法,或者可能是未定义的行为?
让我用一个例子解释一下我想要做什么,这里是函数:
void
gkUpdateTransforms(GkNode *node /* other params */) {
GkNode *nodei;
if (!(nodei = node->chld))
return;
do {
/* do job */
nodei = nodei->next;
} while (nodei);
}
Run Code Online (Sandbox Code Playgroud)
选择:
void
gkUpdateTransforms2(GkNode *node /* other params */) {
/* node parameter is only used here to get chld, not anywhere else */
if (!(node = node->chld))
return;
do {
/* do job */
node = node->next;
} while (node);
}
Run Code Online (Sandbox Code Playgroud)
我检查了程序集输出,看起来是一样的,我们不需要在第二个输出中声明变量。您可能会问,如果参数类型发生变化,但第一个条件相同怎么办,因为它也需要更新。
编辑:参数是按值传递的,我的目的不是编辑指针本身
EDIT2:递归函数怎么样?如果 gkUpdateTransforms2 是递归的,会发生什么?我很困惑,因为函数会调用自身,但我认为在每次调用中,参数都会有不同的堆栈
我不知道为什么你认为这是未定义的行为 - 事实并非如此。主要是编码风格的问题,没有明显的对错。
一般来说,将参数视为不可变对象是一种很好的做法。保留函数输入的未更改副本很有用。因此,使用只是参数副本的局部变量可能是个好主意。正如您所看到的,这丝毫不会影响性能——编译器会优化代码。
不过,如果你写入参数也没什么大不了的。这也是常见的做法。称这样做是不好的做法是非常迂腐的。
一些迂腐的编码风格使所有函数参数const都不应被修改,但我个人认为这只是混淆,这使得代码更难阅读。在你的情况下,这种迂腐的风格就是void gkUpdateTransforms(GkNode*const node)。不要与 const 正确性相混淆,这是一件普遍的好事,而不仅仅是风格问题。
但是,您的代码中的某些内容绝对被认为是不好的做法,那就是条件内的赋值。尽可能避免这种情况,它很危险并且会使代码更难阅读。大多数情况下没有任何好处。
=混淆的危险==在 C 语言的历史中很早就被注意到。为了解决这个问题,在 20 世纪 80 年代,人们想出了像“尤达条件”这样的大脑损伤的东西。然后在 1989 年左右出现了 Borland Turbo C,它有一个奇特的警告功能“可能的错误分配”。这就是 Yoda 条件的消亡,从那时起,编译器就警告不要在条件中进行赋值。
确保您当前的编译器对此发出警告。也就是说,确保不要使用比 1989 年的 Borland Turbo 更糟糕的编译器。是的,市场上有更糟糕的编译器。
(gcc 给出“警告:建议在用作真值的赋值周围使用括号”)
我会把代码写成
void gkUpdateTransforms(GkNode* node /* other params */)
{
if(node == NULL)
{
return ;
}
for(GkNode* i=node->chld; i!=NULL; i=i->next;)
{
/* do job */
}
}
Run Code Online (Sandbox Code Playgroud)
这主要是风格上的改变,以使代码更具可读性。它并不能提高太多性能。