unix

格式化输出是由5个printf 函数来处理的

#include <stdio.h>
int printf(const char *restrict format, ...);
int fprintf(FILE *restrict fp, const char *restrict format, ...);
int dprintf(int fd, const char *restrict format, ...);
int sprintf(char *restrict buf, const char *restrict format, ...);
int snprintf(char *restrict buf, size_t n, const char *restrict format, ...);

printf将格式化数据写到标准输出
fprintf写至指定的流
dprintf写至指定的文件描述符
sprintf将格式化字符写入buf中。 sprintf在该字符串的文段自动加上一个NULL,但该字节不包括在返回值中
注意,sprintf函数可能会造成有buf指向的缓冲区的溢出。
为了解决缓冲区溢出安全隐患,引入了snprintf函数,超过缓冲区尾端写的所有字符都被丢弃。与sprintf相同,该返回值不包括结尾的null字节。

printf的变体: 可变参数(...)替换成arg

#include <stdarg.h>
#include <stdio.h>
int vprintf(const char *restrict format, va_list arg);
int vfprintf(FILE *restrict fp, const char *restrict format, va_list arg);
int vdprintf(int fd, const char *restrict format, va_list arg);
int vsprintf(char *restrict buf, const char *restrict format, va_list arg);
int vsnprintf(char *restrict buf, size_t n, const char *restrict format, va_list arg);

格式化输入,3个scanf函数

#include <stdio.h>
int scanf(const char *restrict format, ...);
int fscanf(FILE *restrict fp, const char *restrict format, ...);
int sscanf(char *restrict buf, const char *restrict format, ...);

可变参数

#include <stdarg.h>

int VarArgFunc(int dwFixedArg, ...){ //以固定参数的地址为起点依次确定各变参的内存起始地址

    va_list pArgs = NULL;  //定义va_list类型的指针pArgs,用于存储参数地址

    va_start(pArgs, dwFixedArg); //初始化pArgs指针,**使其指向第一个可变参数。该宏第二个参数是变参列表的前一个参数,即最后一个固定参数**

    int dwVarArg = va_arg(pArgs, int); //该宏返回变参列表中的当前变参值并使pArgs指向列表中的下个变参。该宏第二个参数是要返回的当前变参类型

    //若函数有多个可变参数,则依次调用va_arg宏获取各个变参

    va_end(pArgs);  //将指针pArgs置为无效,结束变参的获取

    /* Code Block using variable arguments */

}

//可在头文件中声明函数为extern int VarArgFunc(int dwFixedArg, ...);,调用时用VarArgFunc(FixedArg, VarArg);

stdarg.h头文件内变参宏定义如下:

typedef char * va_list;

#define _INTSIZEOF(n)       ( (sizeof(n)+sizeof(int)-1) & ~(sizeof(int)-1) )

#define va_start(ap,v)        ( ap = (va_list)&v + _INTSIZEOF(v) )

#define va_arg(ap, type)    ( *(type *)((ap += _INTSIZEOF(type)) - _INTSIZEOF(type)) )

#define va_end(ap)             ( ap = (va_list)0 )

示例:

#include <stdio.h>
#include <stdarg.h>
 
double average(int num,...)
{
 
    va_list valist;
    double sum = 0.0;
    int i;
 
    /* 为 num 个参数初始化 valist */
    va_start(valist, num);
 
    /* 访问所有赋给 valist 的参数 */
    for (i = 0; i < num; i++)
    {
       sum += va_arg(valist, int);
    }
    /* 清理为 valist 保留的内存 */
    va_end(valist);
 
    return sum/num;
}
 
int main()
{
   printf("Average of 2, 3, 4, 5 = %f
", average(4, 2,3,4,5));
   printf("Average of 5, 10, 15 = %f
", average(3, 5,10,15));
}

习题:
下面的代码在一些机器上运行正确,而在另一些机器上运行时出错,解释问题所在

#include <stdio.h>
int main(void)
{
  char c;
  while((c=getchar())!=EOF)
    putchar(c);
}

答案:
getchar返回值为int型,当系统的char型为有符号型时能正常运行,当系统的char为无符号型时,EOF 不再是-1, 运行死循环

int getchar(void);
原文地址:https://www.cnblogs.com/feiwatson/p/15373990.html