當前位置:編程學習大全網 - 源碼下載 - printf函數的實現方式

printf函數的實現方式

其實printf和getchar()類似,它們都是壹個”外殼“,真正實現功能的不是它本身,而是通過調用別的函數。

getchar() is equivalent to getc(stdin).

printf有壹家子print函數

printf, fprintf, sprintf, snprintf, vprintf, vfprintf, vsprintf, vsnprintf - formatted output conversion

它們的聲明在不同的header file裏面

#include <stdio.h>

int printf(const char *format, ...);

int fprintf(FILE *stream, const char *format, ...);

int sprintf(char *str, const char *format, ...);

int snprintf(char *str, size_t size, const char *format, ...);

#include <stdarg.h>

int vprintf(const char *format, va_list ap);

int vfprintf(FILE *stream, const char *format, va_list ap);

int vsprintf(char *str, const char *format, va_list ap);

int vsnprintf(char *str, size_t size, const char *format, va_list ap);

snprintf(), vsnprintf():

這兩個函數是C99新加的,編譯的時候 註意 -std=c99

實現之前還是“復習”壹下printf比較好,就當是鋪墊

有意思的是printf的declaration。

int printf(const char *format, ...);

返回值是int,第壹個參數是const字符串指針,第二個參數是個...

先看看返回值int有哪些情況

Return value

Upon successful return, these functions return the number of characters printed (excluding the null byte used to end output to strings).

嗯哼。。。返回的是成功打印的字符的個數,這裏不包括NULL

demo:

#include<stdio.h>

int main()

{

int counter = 0;

counter = printf("hello world! %d\n",10);

printf("counter is %d\n",counter);

return 0;

}

jasonleaster@ubuntu:~$ ./a.out

hello world! 10

counter is 16

接著,第壹個參數是壹個指針,指向const字符串

Format of the format string

The format string is a character string, beginning and ending in its initial shift state, if any. The format string is composed of

zero or more directives: ordinary characters (not %), which are copied unchanged to the output stream; and conversion specifications,

each of which results in fetching zero or more subsequent arguments. Each conversion specification is introduced by the character %,

and ends with a conversion specifier. In between there may be (in this order) zero or more flags, an optional minimum field width,

an optional precision and an optional length modifier.

很少人會用下面這種用法

printf("%*d",10,5);

我第壹次遇到的時候,可以說是“驚愕”,究竟會打印什麽東西。折騰了好久,最後搞定了。總結在這裏

posed of zero or more directives: ordinary characters (not %), which are copied unchanged to the output stream; and conversion specifications, each of which results in fetching zero or more subsequent arguments. Each conversion specification is introduced by the character %, and ends with a conversion specifier. In between there may be (in this order) zero or more flags, an optional minimum field width, an optional precision and an optional length modifier.

The arguments must correspond properly (after type promotion) with the conversion specifier. By default, the arguments are used in the order given, where each '*' and each conversion specifier asks for the next argument (and it is an error if insufficiently many arguments are given). One can also specify explicitly which argument is taken, at each place where an argument is required, by writing "%m$" instead of '%' and "*m$" instead of '*', where the decimal integer m denotes the position in the argument list of the

desired argument, indexed starting from 1. Thus,

printf("%*d", width, num);

and

printf("%2$*1$d", width, num);

are equivalent. The second style allows repeated references to the same argument. The C99 standard does not include the style using '$', which comes from the Single UNIX Specification. If the style using '$' is used, it must be used throughout for all conversions taking an argument and all width and precision arguments, but it may be mixed with "%%" formats which do not consume an argument.

There may be no gaps in the numbers of arguments specified using '$'; for example, if arguments 1 and 3 are specified, argument 2

must also be specified somewhere in the format string.

第三個參數 ...

嗯,這家夥有點屌,叫做變長參數。把這個搞定,C總會有點長進的

這個stdarg.h 我在現在的GCC和現在的linux 3.0版本的內核裏面找了好久,都木有,估計是封裝到被的地方了。。。。

__builtin_va_start(v,l) 線索就死在這個地方。。。之後就找不到__builtin_va_start的定義了

還是看早起內核的實現吧

0.12內核裏面的stdarg.h

#ifndef _STDARG_H

#define _STDARG_H

typedef char *va_list;

/* Amount of space required in an argument list for an arg of type TYPE.

TYPE may alternatively be an expression whose type is used. */

#define __va_rounded_size(TYPE) \

(((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int))

#ifndef __sparc__

#define va_start(AP, LASTARG) \

(AP = ((char *) &(LASTARG) + __va_rounded_size (LASTARG)))

#else

#define va_start(AP, LASTARG) \

(__builtin_saveregs (), \

AP = ((char *) &(LASTARG) + __va_rounded_size (LASTARG)))

#endif

void va_end (va_list); /* Defined in gnulib */

#define va_end(AP)

#define va_arg(AP, TYPE) \

(AP += __va_rounded_size (TYPE), \

*((TYPE *) (AP - __va_rounded_size (TYPE))))

#endif /* _STDARG_H */

va_list 是壹個指向字符串的指針

分析上面的宏定義#define __va_rounded_size(TYPE) \

(((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int))

這個用來得到TYPE元素類型的字節大小,若不足4字節(例如short 和char),那麽認為這個元素的大小為4字節,簡單的說就是檢測元素的大小,不足4字節的當作4字節看待。。。#define va_start(AP, LASTARG) \

(AP = ((char *) &(LASTARG) + __va_rounded_size (LASTARG)))

AP壹般都是va_list,LASTARG則是 指向參數變長函數的格式化字符串的指針.

va_start的作用就很明顯了。取得變長參數列表的第壹個參數的地址。

va_end 則是把指針va_list 置0 (通過google知道的,這個va_end真沒找到定義,代碼裏面就壹句#define 我無能為力啊。。。)

不過知道用va_start 和va_end 就OK啦

下面先來個變長參數的demo

/*****************************************************************************

code writer : EOF

code date : 2014.04.26

e-mail:jasonleaster@gmail.com

code purpose:

just a demo for varible parameter function.

usage: va_sum(a number,anohter number...,0);

va_sum(1,2,3,4,5,0); return 15

******************************************************************************/

#include <stdarg.h>

#include <stdio.h>

int va_sum(int* a,...);

int main()

{

int number = 1;

int foo = 0;

foo = va_sum(&number,2,3,4,5,0);

return 0;

}

int va_sum(int* a,...)

{

int counter = 0;

int element = 0;

va_list arg;

va_start(arg,a);

while((element = va_arg(arg,int)) != 0)

{

counter += element;

}

va_end(arg);

return counter;

}

#define va_arg(AP, TYPE) \

(AP += __va_rounded_size (TYPE), \

*((TYPE *) (AP - __va_rounded_size (TYPE))))

  • 上一篇:Delphi獲取網頁源代碼
  • 下一篇:越獄第三季10到13劇情
  • copyright 2024編程學習大全網