目标是帮助其他程序员编写可读性。
在创建函数原型时,我倾向于将简单类型(int,char)直接放入原型中,而更复杂的结构通常作为指针传递(struct complex *)。
当然,这通常是#34;并且有一些明显的反例:如果函数必须修改一个简单的参数,则将指针传递给它。
但是现在,假设在我的函数参数中,我得到一个复杂但不那么庞大的结构,在只读模式下传递(它不会被修改)。到目前为止,我会做这样的事情:
int myFunction1(int var1, const complexStruct* var2Ptr);
当然可行。但是现在,我想知道,因为结构的内容无论如何都不会被修改,而是定义这样的函数原型会更好:
int myFunction2(int var1, complexStruct var2);
很难说。我的胆量告诉我myFunction2可能更容易阅读,因此使用,特别是新手程序员,往往不喜欢指针。经验丰富的程序员可能不会介意。
我还猜测,作为参数列表的一部分复制到堆栈的数据量对于myFunction2来说会更高(假设myFunction2不会被编译器自动内联)。当然,只要complexStruct不是太大,它就不应该成为问题。但这意味着结构的大小是决定因素。
最后,我想myFunction2可能更容易由编译器内联。但那只是一个疯狂的猜测。
无论如何,由于两个函数原型看起来都是等价的,我对于哪个函数原型可能更为可能有点无能为力,并且想知道是否还有其他考虑因素,可能更重要的是要考虑决策。
到目前为止收到的评论摘要:
简而言之,在大多数情况下更喜欢const struct *。
答案 0 :(得分:1)
特别是对于“属于”某种数据类型的函数,我更喜欢将指针作为第一个参数传递(如C ++中的this
指针)。它还使变异和非变异函数的签名更加一致。
考虑使用struct stack
,stack_push
(变异)和(非变异)stack_pop
函数的stack_top
。类型可能小到
struct stack
{
size_t capacity_;
size_t size_;
char * data_;
};
所以我们不应该担心复制几个字。 (它实际上可能比取消引用非本地指针更快。)
不过,我发现这套“会员功能”
extern int stack_init(struct stack * this);
extern int stack_deinit(struct stack * this);
extern int stack_push(struct stack * this, char value);
extern int stack_pop(struct stack * this);
extern int stack_top(const struct stack * this);
extern int stack_size(const struct stack * this);
void
usage_example()
{
struct stack mystack;
if (stack_init(&mystack) < 0) { /* handle error */ }
if (stack_push(&mystack, 'a') < 0) { /* handle error */ }
assert(stack_top(&mystack) == 'a');
assert(stack_size(&mystack) == 1);
stack_deinit(&mystack);
}
比这个更加一致:
extern int stack_init(struct stack * this);
extern int stack_deinit(struct stack * this);
extern int stack_push(struct stack * this, char value);
extern int stack_pop(struct stack * this);
/* Duckling asks: What is the difference between 'this' and 'self'? */
extern int stack_top(struct stack self);
extern int stack_size(struct stack self);
void
usage_example()
{
struct stack mystack;
if (stack_init(&mystack) < 0) { /* handle error */ }
if (stack_push(&mystack, 'a') < 0) { /* handle error */ }
/* Duckling asks: Are you sure you didn't forget the '&' here? */
assert(stack_top(mystack) == 'a');
assert(stack_size(mystack) == 1);
stack_deinit(&mystack);
}
如果可能的话,我认为某些东西是const
的事实应该是编译器的关注,而不是强迫程序员使用另一个调用约定。
这与问题无关,但万一有人问:stack_top
和stack_pop
函数的返回值是相应的字符,或者是下溢的-1。其他函数在成功时返回0,在错误时返回负错误代码(例如内存不足)。