C语言中fgetc、fputc和getc、putc的区别是什么
看书的时候,发现了这四个函数,想知道他们的不同。结果上网查发现很多人说fgetc、fputc的f代表的是file,就是这两个函数是和文件有关的!但是一看他们的函数声明,如下图:




发现他们的参数里面都有文件指针啊!后来又去翻了翻APUE,发现那个f代表的其实是function,这是怎么一回事呢,且听我慢慢道来!
fgetc和getc他们的区别并不是在他们的使用上,而是在他们的实现上!具体来说,就是带f的(fgetc、fputc)实现的时候是通过函数来实现的,而不带f(putc、getc)的,实现的时候是通过宏定义来实现的!关于他们的不同点,就拿getc和fgetc来说,APUE(p115)上是这么写的:
<1>.getc的参数不应当是具有副作用的表达式。
<2>.因为fgetc一定是一个函数,所以可以得到其地址。这就允许将fgetc的地址作为一个参数传送给另一个函数。
<3>.调用fgetc所需时间很可能长于调用getc,因为调用函数通常所需的时间长于调用宏。
首先说第一点应该怎么理解呢,这个是因为宏这个东西坑蛮多,这里举个经典的例子。

在这个程序中,z2我想算8*8,但是传入的参数是5+3,6+2,宏替换之后就变成了5+3*6+2,最后结果就成了25。
那么第二点又是什么意思呢,这个其实就是一个函数指针,一个函数的地址能够传递给一个函数指针,让其来调用,但是宏就不行了!比如说下面这段代码:

由于MAX是个宏,所以就不能赋值给函数指针了!
关于第三点,这就涉及到一点汇编的知识了,在汇编语言中,函数的调用是通过栈来实现的!就是调用的时候压栈,调用完了再弹栈(关于汇编我也不是很清楚,所以叙述的有点粗糙,还望见谅!),比如下面这段代码:
#include<stdio.h>
void func3()
{
printf("Hello,World!");
}
void func2()
{
func3();
}
void func1()
{
func2();
}
int main(int argc,char *argv[])
{
func1();
return ;
}
我用gdb调试,在第4行设置了一个断点,查看它的函数调用栈如下:

而通过宏调用是不用压栈的,所以getc的速度就比fgetc快那么一点。
不过,关于这个是有一点例外,就是有时候调用函数并不是通过栈来实现的,所以作者用了一个很可能的词汇。关于这个问题,这个帖子讲的非常好(fgetc和getc,哪个速度快?)。
OK,上面就是fgetc和getc的不同了!不过需要补充一点的是关于GNU C下这两个函数其实是一样的,他们都是通过函数来实现的,然后getc再简单粗暴地增加了一个宏的声明。具体如下:
在stdio.h这个文件中getc的声明是这样的:

而在libio.h里面那个_IO_getc (_fp)这个函数的声明又是这样的:

所以,最后,各位亲们,我想说的是,不要再纠结了,这两个函数敞开了用吧,区别不是很大,一般不会出啥问题的!
C语言中fgetc、fputc和getc、putc的区别是什么的更多相关文章
- C语言中fgetc函数返回值为什么是int?
学习C语言的,文件操作,大都会用到它. 它的函数原型: 这个函数的返回值,是返回读取的一个字节.如果读到文件末尾返回EOF.EOF其实就是一个宏#define EOF (-1)表示-1.既然返回的是一 ...
- C语言中file文件指针概念及其操作 (转载)
文件 文件的基本概念 所谓"文件"是指一组相关数据的有序集合. 这个数据集有一个名称,叫做文件名.实际上在前面的各章中我们已经多次使用了文件,例如源程序文件.目标文件.可执行文件. ...
- C语言中,头文件和源文件的关系(转)
简单的说其实要理解C文件与头文件(即.h)有什么不同之处,首先需要弄明白编译器的工作过程,一般说来编译器会做以下几个过程: 1.预处理阶段 2.词法与语法分析阶段 3.编译阶段,首先编译成纯汇编语句, ...
- C 语言中 setjmp 和 longjmp
在 C 语言中,我们不能使用 goto 语句来跳转到另一个函数中的某个 label 处:但提供了两个函数——setjmp 和 longjmp来完成这种类型的分支跳转.后面我们会看到这两个函数在处理异常 ...
- c语言中的scanf在java中应该怎么表达,Scanner类。
1 java是面向对象的语言 它没有像C语言中的scanf()函数,但是它的类库中有含有scanf功能的函数 2 java.util包下有Scanner类 Scanner类的功能与scanf类似 3 ...
- C语言中do...while(0)的妙用(转载)
转载来自:C语言中do...while(0)的妙用,感谢分享. 在linux内核代码中,经常看到do...while(0)的宏,do...while(0)有很多作用,下面举出几个: 1.避免goto语 ...
- C语言中,定义的含义?声明的含义?它们之间的区别是什么?
在C语言中,对于定义和声明,也许我们非常的熟悉,但不一定真正的了解! 定义的含义:所谓定义,就是创建(编译器)一个对象,为这个对象分配一块内存空间并取名,也就是我们平常所说的变量名或对象名,一旦这个名 ...
- C++中函数的默认参数和C语言中volatile的学习
1.函数默认参数 1 int func(int a,int b=10) 2 { 3 return a*b; 4 } 5 6 int main() 7 { 8 int c=func(2); 9 cout ...
- C语言中qsort函数用法
C语言中qsort函数用法-示例分析 本文实例汇总介绍了C语言中qsort函数用法,包括针对各种数据类型参数的排序,非常具有实用价值非常具有实用价值. 分享给大家供大家参考.C语言中的qsort ...
随机推荐
- Java 计算两个日期相差月数
package com.myjava; import java.text.ParseException;import java.text.SimpleDateFormat;import java.ut ...
- C#多线程交替赋值取值
static AutoResetEvent auto=new AutoResetEvent(false); ; ; static void Main() { Thread th1 = new Thre ...
- Python学习 之 爬虫
目标:下载贴吧或空间中所有图片 步骤:(1)获取页面代码 (2)获取图片URL,下载图片 代码如下: #!/usr/bin/python import re import urllib def get ...
- 网络IPC:套接字之带外数据
带外数据(Out-of-band data)是一些通信协议所支持的可选特征,允许更高优先级的数据比普通数据优先传输.即使传输队列已经有数据,带外数据先行传输.TCP支持带外数据,但是UDP不支持.套接 ...
- MongoDB笔记--安装篇
安装MongoDB 第一步:下载安装包:官方下载地址←单击此处,如果是win系统,注意是64位还是32位版本的,请选择正确的版本. 第二步:新建目录“D:\MongoDB”,解压下载到的安装包,找到b ...
- TortoiseGit安装和使用的图文教程
ortoiseGit是Windows下不错的一款Git客户端工具,在Mac下推荐使用sourcetree.下面就介绍一下TortoiseGit安装和使用的方法. 安装TortoiseGit并使用它需要 ...
- rpm命令使用说明
RPM是RedHat Package Manager(RedHat软件包管理工具)类似Windows里面的“添加/删除程序” rpm 执行安装包二进制包(Binary)以及源代码包(Source)两种 ...
- Active Session History (ASH) Performed An Emergency Flush Messages In The Alert Log
Active Session History (ASH) Performed An Emergency Flush Messages In The Alert Log (文档 ID 1385872.1 ...
- PLS-00201: 必须声明标识符 'UTL_FILE'
解决办法: 用sysdba身份 把UTL_FILE包的执行权限给这个用户. 举例: 1.C:\Users\Anakin>sqlplus /nolog2.SQL> connect /as s ...
- CF 13E. Holes 分块数组
题目:点这 跟这题BZOJ 2002: [Hnoi2010]Bounce 弹飞绵羊 一模一样 分析: 分块数组入门题. 具体的可以学习这篇博文以及做国家集训队2008 - 苏煜<对块状链表的一 ...