为什么 fputs() 需要一个常量作为第一个参数而不是 fputc()?
Why does fputs() require a constant as first parameter and not fputc()?
int fputc(int c, FILE *stream);
int fputs(const char *s, FILE *stream);
为什么 fputc() 的声明中不需要 const int c
?
第一个参数不用做const
; "top level" 个参数被复制,而不是被引用,所以 const
要做的就是防止被调用函数修改它自己的参数副本。
同样,请注意只有指向的值是 const
for fputs
;该参数不是 const char *const s
因为额外的 const-ness 只会限制被调用者修改其指针副本指向的位置的能力; const
保证仅适用于指向的(共享)值。
在函数声明中将参数标记为 const
没有意义。参数按值传递,因此参数无论如何都是一个副本。它不影响函数的调用方式。
但是,const char *s
不代表s
就是const
。这个声明的意思是 s
是一个指向 const char
的指针;即 fputs
函数承诺不会通过给定的指针进行写入。此外,还有从 char *
到 const char *
的隐式转换(反之亦然),这意味着 fputs
可以用只读和可写字符串调用。
const
修饰符防止函数改变输入参数。
fputc
函数使用 int c
作为值类型的输入。因为参数是按值传递的,函数只能改变内部副本,不能改变原来的值。
fputs
函数使用char *s
作为指针类型的输入,所以指向的内存可以被函数改变。 const
修饰符通过防止函数更改它来保护指向的内存。
注1:函数fputs
中的const
修饰符在char
类型(const char *s
)上,即表示无法更改指向的内存。如果 const
在输入参数 s
(char * const s
) 上,它不会保护指向的内存,它只会保护无论如何按值传递的指针本身。
注2:如Eric Postpischil in the comment and shown in Vlad from Moscow's 所述,如果const修饰符在函数声明中而不是在函数定义中,则没有作用。
const char *s
并不意味着 s
必须指向一个常量。这意味着 fputs
不允许修改 s
.
指向的内容
当编译器确定函数类型时,高级参数限定符将被丢弃。
所以这两个函数声明
int fputc(int c, FILE *stream);
int fputc( const int c, FILE *stream);
声明同一个函数。
以及这两个函数声明
int fputs(const char *s, FILE *stream);
int fputs(const char * const s, FILE *stream);
同样声明一个函数。
因此高级限定符const 对函数的用户没有意义,只对函数的内部定义有意义。在任何情况下,相应的参数都是按值传递的,即函数处理参数的副本。因此,对于函数的用户而言,副本是否在函数内部具有限定符 const 并不重要。
考虑以下演示程序
#include <stdio.h>
void f( const int x );
void f( int x )
{
x += 10;
printf( "Inside the function x = %d\n", x );
}
int main( void )
{
int x = 1;
printf( "Before calling f x = %d\n", x );
f( x );
printf( "After calling f x = %d\n", x );
}
它的输出是
Before calling f x = 1
Inside the function x = 11
After calling f x = 1
所以对于函数的使用者来说函数的参数x是否有限定符const并不重要。从编译器(和函数的用户)的角度来看,这两个声明都声明了同一个函数。
函数参数是它们的局部变量。并且用户不关心某些局部变量是否会在带有限定符 const 的函数中声明。
注意本声明中的内容
int fputs(const char *s, FILE *stream);
它不是第一个声明为常量的参数。指针指向的数据是常量。
但是在这个声明中
int fputc( const int c, FILE *stream);
参数本身是常量。
int fputc(int c, FILE *stream);
int fputs(const char *s, FILE *stream);
为什么 fputc() 的声明中不需要 const int c
?
第一个参数不用做const
; "top level" 个参数被复制,而不是被引用,所以 const
要做的就是防止被调用函数修改它自己的参数副本。
同样,请注意只有指向的值是 const
for fputs
;该参数不是 const char *const s
因为额外的 const-ness 只会限制被调用者修改其指针副本指向的位置的能力; const
保证仅适用于指向的(共享)值。
在函数声明中将参数标记为 const
没有意义。参数按值传递,因此参数无论如何都是一个副本。它不影响函数的调用方式。
但是,const char *s
不代表s
就是const
。这个声明的意思是 s
是一个指向 const char
的指针;即 fputs
函数承诺不会通过给定的指针进行写入。此外,还有从 char *
到 const char *
的隐式转换(反之亦然),这意味着 fputs
可以用只读和可写字符串调用。
const
修饰符防止函数改变输入参数。
fputc
函数使用 int c
作为值类型的输入。因为参数是按值传递的,函数只能改变内部副本,不能改变原来的值。
fputs
函数使用char *s
作为指针类型的输入,所以指向的内存可以被函数改变。 const
修饰符通过防止函数更改它来保护指向的内存。
注1:函数fputs
中的const
修饰符在char
类型(const char *s
)上,即表示无法更改指向的内存。如果 const
在输入参数 s
(char * const s
) 上,它不会保护指向的内存,它只会保护无论如何按值传递的指针本身。
注2:如Eric Postpischil in the comment and shown in Vlad from Moscow's
const char *s
并不意味着 s
必须指向一个常量。这意味着 fputs
不允许修改 s
.
当编译器确定函数类型时,高级参数限定符将被丢弃。
所以这两个函数声明
int fputc(int c, FILE *stream);
int fputc( const int c, FILE *stream);
声明同一个函数。
以及这两个函数声明
int fputs(const char *s, FILE *stream);
int fputs(const char * const s, FILE *stream);
同样声明一个函数。
因此高级限定符const 对函数的用户没有意义,只对函数的内部定义有意义。在任何情况下,相应的参数都是按值传递的,即函数处理参数的副本。因此,对于函数的用户而言,副本是否在函数内部具有限定符 const 并不重要。
考虑以下演示程序
#include <stdio.h>
void f( const int x );
void f( int x )
{
x += 10;
printf( "Inside the function x = %d\n", x );
}
int main( void )
{
int x = 1;
printf( "Before calling f x = %d\n", x );
f( x );
printf( "After calling f x = %d\n", x );
}
它的输出是
Before calling f x = 1
Inside the function x = 11
After calling f x = 1
所以对于函数的使用者来说函数的参数x是否有限定符const并不重要。从编译器(和函数的用户)的角度来看,这两个声明都声明了同一个函数。
函数参数是它们的局部变量。并且用户不关心某些局部变量是否会在带有限定符 const 的函数中声明。
注意本声明中的内容
int fputs(const char *s, FILE *stream);
它不是第一个声明为常量的参数。指针指向的数据是常量。
但是在这个声明中
int fputc( const int c, FILE *stream);
参数本身是常量。