我正在阅读"C语言编程"一书,并在第10章中找到了这样一个例子:
#include <stdio.h>
void test (int *int_pointer)
{
*int_pointer = 100;
}
int main (void)
{
void test (int *int_pointer);
int i = 50, *p = &i;
printf ("Before the call to test i = %i\n", i);
test (p);
printf ("After the call to test i = %i\n", i);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我理解这个例子,但我不明白其中void test (int *int_pointer);的内容main.为什么我要test再次定义签名?这是惯用的C吗?
hac*_*cks 11
void test (int *int_pointer);只是函数的声明(或原型)test.不需要这个声明main因为你之前已经有了函数定义main.
如果定义test是在main那之后那么值得将其声明放在那里让编译器test在调用它之前知道返回类型,参数数量和参数类型.
han*_*rak 11
它绝对不是惯用的C,尽管它是完全有效的(多个声明是可以的,多个定义不是).这是不必要的,所以如果没有它,代码仍然可以正常工作.
如果有的话,也许是作者的意思
void test (int *int_pointer);
int main (void) {
...
}
Run Code Online (Sandbox Code Playgroud)
以防函数定义放在后面main ().
它完全是惯用的C,它实际上具有(有限的)实际用途 - 尽管不是这个例子所证明的.
当您在通常的全局级别声明函数或其他名称时,它将被引入声明后面的代码中的所有函数体.一旦引入声明,就无法从作用域中删除声明.该功能对翻译单元的其余部分始终可见.
在支撑块中声明函数或其他名称时,声明的范围仅限于该块.声明另一个函数范围内的函数将限制其可见性,并且不会污染全局命名空间或使其对同一翻译单元中定义的任何其他函数可见.
在示例的情况下,这是毫无意义的,因为定义test也将它带入所有后续主体的范围 - 但如果test在另一个转换单元中定义,或者即使它仅在此TU的最底部定义,则隐藏声明内部main将保护之后定义的任何其他函数,使其无法在其范围内查看其名称.
实际上,这是有限的使用 - 通常如果你不想看到一个功能,你把它放在另一个翻译单元(最好是它static) - 但你可能会设想你可能想要使用它的情况构建不导出其组件的原始声明的模块加载系统的能力,或类似的东西(以及这不依赖于static/单独的目标文件的事实可能与嵌入/非托管的某些相关链接步骤可能无法像在PC上那样工作的目标环境,允许您在纯粹#include的构建系统中实现名称空间保护措施.
例:
struct module {
void * (* alloc)(size_t);
void (* dealloc)(void *);
} loaded_module;
int main(void) {
if (USE_GC) { // dynamically choose the allocator system
void * private_malloc_gc(size_t);
void private_free_noop(void *);
loaded_module = (struct module){ private_malloc_gc, private_free_noop };
} else {
void * private_malloc(size_t);
void private_free(void *);
loaded_module = (struct module){ private_malloc, private_free };
}
do_stuff();
//...
}
// cannot accidentally bypass the module and manually use the wrong dealloc
void do_stuff(void) {
int * nums = module.alloc(sizeof(int) * 32)
//...
module.dealloc(nums);
}
#include "allocator_implementations.c"
Run Code Online (Sandbox Code Playgroud)