其他知识点
printf族函数
#include <stdio.h>
#include <math.h>
#include <ctype.h>
int main(void)
{
printf("%u
",-34);
short c;
//short与char类型的参数会被自动扩展为int型,因此-37转换为无符号整数时
//会出错,由于short转换为int类型从小转换为大,因此需要填充符号位.由于-37的
//最高符号位为1,输出为无符号整数时前面会自动填充为0,因此输出结果为4294967259这个极大正整数
c=-37;
printf("%u
",c);
int n=1;
printf("%d decimal=%o octal= %X hex
",n,n,n);
//%s格式项所对应输出的字符串必须以一个空字符' '作为结束标识
printf("There %s %d item%s in the list.
",n!=1?"are" :"is",n,n!=1?"s":"");
//printf(s);
//printf("%s",s);
//NULL所指向的内容不能企图使用该指针所指向的内存中存储的内容
printf("%s
",NULL);
printf("The decimal equivalent of '%c' is %d
",'*','*');
printf("Pi=%g
",4*atan(1.0));
printf("%g %g %g %g %g
",1/1.0,1/2.0,1/3.0,1/4.0,0.0);
printf("%g
",2.0/3.0);
printf("%g
",123456789.0);
//对于比较小的数值,除非该数的指数小于或等于-5,%g格式项才会采用科学记数法来表示
printf("%g %g %g
",3.14159e-3,3.14159e-4,3.14159e-5);
printf("%f
",1e38);
//%%用于打印一个%字符
printf("%%d prints a decimal value
");
//在某些机器中,以同样精度存储int型和long型的数值
long size=5;
printf("%d
",size);
printf("%ld
",size);
printf("%*%
",-5);
char str[]="jkagkj";
printf("%*.*s
",12,5,str);
//新增的格式码为%p与%u
int g;
printf("hello
%n",&g);
//print
return 0;
}
putc宏解析###
宏putc在库文件stdio.h中的详细定义如下:
__CRT_INLINE int __cdecl __MINGW_NOTHROW putc (int __c, FILE* __F)
{
return (--__F->_cnt >= 0)
? (int) (unsigned char) (*__F->_ptr++ = (char)__c)
: _flsbuf (__c, __F);
}
其中putc的第一个参数为_c,是将要写入文件的字符,第二个参数__F则为一个指向一个用于描述文件的内部数据结构的指针,这里的__c由于是在条件表达式:的两侧,所以只会被求值一次,不会出现问题.
而__F这个指针,代表将要写入字符的文件,总是会被求值两次,但是由于它一般不需要进行递增递减之类有副作用的操作.但是这样也会出现一些错误.
short,char类型自动转换为int类型###
#include <stdio.h>
int main(void)
{
printf("%u
",-34);
short c;
//short与char类型的参数会被自动扩展为int型,因此-37转换为无符号整数时
//会出错,由于short转换为int类型从小转换为大,因此需要填充符号位.由于-37的
//最高符号位为1,输出为无符号整数时前面会自动填充为0,因此输出结果为4294967259这个极大正整数
c=-37;
printf("%u
",c);
return 0;
}
printf函数可变参数列表实现机制###
#define va_dcl int va_alist;
#define va_start(list) list=(char *) &va_alist
#define va_end(list)
#define va_arg(list,mode) ((mode*) (list +=sizeof(mode))) [-1]
va_list是一个简单的字符型指针,宏va_start把它的参数设定为va_list的地址.
va_arg(list,mode),返回由va_list所指向的恰当类型的数值,同时递增va_list,使它指向参数列表中的下一个参数.使用下标-1来存取正确的返回参数.
注意:由于short,long类型和float类型会自动转换为int类型还有double类型,不能制定为mode这个参数的值.
机制2:使用stdarg.h
使用stdarg.h必须至少有一个固定类型的参数,后面可以跟一组未知数目,未知类型的参数.使用stdargs.h函数直接声明其固定参数,把最后一个固定参数作为va_start宏的参数,即以固定参数为基础.
#include <stdio.h>
#include <stdarg.h>
void error(char *format,...)
{
va_list ap;
va_start(ap,format);
fprintf(stderr,"error: ");
vfprintf(stderr,format,ap);
va_end(ap);
fprintf(stderr,"
");
exit(1);
}
EOF解析###
EOF(End of File),即文件结束符.
其定义为:#define EOF (-1).也就是说EOF代表一个整型常量-1,但一般文件的末尾不存在这个结束标识,那它又是如何判断是否到达文件末尾的呢?
1.对于文本文件来说:由于函数读取数据时是不会返回结果为-1的负数的,只有当没有数据可以读取时才会返回EOF,因此可以正常工作。
2.对于二进制文件而言,如果读取的数据为0xFF的话,此时返回值为-1,即EOF,但是这个时候又没有到达文件末尾,造成数据读取读取出现中途中断.
那如果判定二进制文件是否到达文件末尾?
1.在进行数据读取时,将返回的字符型数据定位为整型
若ch为char型,则当将返回值0x 00 00 00 FF返回时,取低8位赋给ch,那么此时ch为-1,此时会误判为到达文件末尾;
而若ch为int型,则当将返回值0x 00 00 00 FF返回时,ch的值为0x 00 00 00 FF,此时ch不为-1,不会误判为文件末尾。
(当然上面所述成立必须是在读取不出错的情况下才成立)
2.使用feof
其函数原型为:
int feof(FILE *fp),若到达文件末尾则返回一个非零值,否则返回0
#define _IOEOF 0x0010
#define feof(_stream) ((_stream)->_flag & _IOEOF)
可知feof函数判断是否到达文件末尾时与_flag这个标志有关。