参数-C 关于printf() 我真的很想问的一个问题!!!!

问题描述

C 关于printf() 我真的很想问的一个问题!!!!

编译器怎样检查 printf () 参数个数的?
刚刚学C 不久,不知道怎么找,于是到这里提问来了。。。
提前谢谢所有回答的人!!! thanks for your time .

解决方案

参考一下这个回答,对你应该有帮助

C中的可变参数研究

一. 何谓可变参数
int printf( const char* format, ...);
这是使用过C语言的人所再熟悉不过的printf函数原型,它的参数中就有固定参数format和可变参数(用”…”表示). 而我们又可以用各种方式来调用printf,如:
printf("%d",value);
printf("%s",str);
printf("the number is %d ,string is:%s", value, str);

二.实现原理
C语言用宏来处理这些可变参数。这些宏看起来很复杂,其实原理挺简单,就是根据参数入栈的特点从最靠近第一个可变参数的固定参数开始,依次获取每个可变参数的地址。下面我们来分析这些宏。在VC中的stdarg.h头文件中,针对不同平台有不同的宏定义,我们选取X86平台下的宏定义:

typedef char va_list;
/
把va_list被定义成char*,这是因为在我们目前所用的PC机上,字符指针类型可以用来存储内存单元地址。而在有的机器上va_list是被定义成void*的*/
#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
/*_INTSIZEOF(n)宏是为了考虑那些内存地址需要对齐的系统,从宏的名字来应该是跟sizeof(int)对齐。一般的sizeof(int)=4,也就是参数在内存中的地址都为4的倍数。比如,如果sizeof(n)在1-4之间,那么_INTSIZEOF(n)=4;如果sizeof(n)在5-8之间,那么_INTSIZEOF(n)=8。*/
#define va_start(ap,v)( ap = (va_list)&v + _INTSIZEOF(v) )
/*va_start的定义为 &v+_INTSIZEOF(v) ,这里&v是最后一个固定参数的起始地址,再加上其实际占用大小后,就得到了第一个可变参数的起始内存地址。所以我们运行va_start(ap, v)以后,ap指向第一个可变参数在的内存地址*/
#define va_arg(ap,t) ( (t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
/
这个宏做了两个事情,
①用用户输入的类型名对参数地址进行强制类型转换,得到用户所需要的值
②计算出本参数的实际大小,将指针调到本参数的结尾,也就是下一个参数的首地址,以便后续处理。*/
  #define va_end(ap) ( ap = (va_list)0 )
/*x86平台定义为ap=(char*)0;使ap不再 指向堆栈,而是跟NULL一样.有些直接定义为((void*)0),这样编译器不会为va_end产生代码,例如gcc在linux的x86平台就是这样定义的. 在这里大家要注意一个问题:由于参数的地址用于va_start宏,所以参数不能声明为寄存器变量或作为函数或数组类型. */

以下再用图来表示:

在VC等绝大多数C编译器中,默认情况下,参数进栈的顺序是由右向左的,因此,参数进栈以后的内存模型如下图所示:最后一个固定参数的地址位于第一个可变参数之下,并且是连续存储的。
|——————————————————————————|
|最后一个可变参数 | ->高内存地址处
|——————————————————————————|
...................
|——————————————————————————|
|第N个可变参数 | ->va_arg(arg_ptr,int)后arg_ptr所指的地方,
| | 即第N个可变参数的地址。
|——————————————— |
………………………….
|——————————————————————————|
|第一个可变参数 | ->va_start(arg_ptr,start)后arg_ptr所指的地方
| | 即第一个可变参数的地址
|——————————————— |
|———————————————————————— ——|
| |
|最后一个固定参数 | -> start的起始地址
|—————————————— —| .................
|—————————————————————————— |
| |
|——————————————— |-> 低内存地址处

三.printf研究

下面是一个简单的printf函数的实现,参考了中的156页的例子,读者可以结合书上的代码与本文参照。
#include "stdio.h"
#include "stdlib.h"
void myprintf(char* fmt, ...) //一个简单的类似于printf的实现,//参数必须都是int 类型
{
char* pArg=NULL; //等价于原来的va_list
char c;

pArg = (char*) &fmt; //注意不要写成p = fmt !!因为这里要对//参数取址,而不是取值
pArg += sizeof(fmt); //等价于原来的va_start

do
{
c =*fmt;
if (c != '%')
{
putchar(c); //照原样输出字符
}
else
{
//按格式字符输出数据
switch(*++fmt)
{
case 'd':
printf("%d",*((int*)pArg));
break;
case 'x':
printf("%#x",*((int*)pArg));
break;
default:
break;
}
pArg += sizeof(int); //等价于原来的va_arg
}
++fmt;
}while (*fmt != '');
pArg = NULL; //等价于va_end
return;
}

int main(int argc, char* argv[])
{
int i = 1234;
int j = 5678;

myprintf("the first test:i=%d",i,j);
myprintf("the secend test:i=%d; %x;j=%d;",i,0xabcd,j);
system("pause");
return 0;
}

在intel+win2k+vc6的机器执行结果如下:
the first test:i=1234
the secend test:i=1234; 0xabcd;j=5678;

四.应用
求最大值:
#include //不定数目参数需要的宏
int max(int n,int num,...)
{
va_list x;//说明变量x
va_start(x,num);//x被初始化为指向num后的第一个参数
int m=num;
for(int i=1;i {
//将变量x所指向的int类型的值赋给y,同时使x指向下一个参数
int y=va_arg(x,int);
if(y>m)m=y;
}
va_end(x);//清除变量x
return m;
}

int main()
{
printf("%d,%d",max(3,5,56),max(6,0,4,32,45,533));
return 0;
}

解决方案二:

简单的说,printf 是根据第一个参数中格式化字符的个数来确定的。如果格式化的参数有4个,而后面实际的参数只有3个时,可能会引起严重的错误!

解决方案三:

我也不是很懂,也许可以跟踪到函数里面看看?用跟踪调试

解决方案四:

nt max(int n,int num,...)
{
va_list x;//说明变量x
va_start(x,num);//x被初始化为指向num后的第一个参数
int m=num;
for(int i=1;i {
//将变量x所指向的int类型的值赋给y,同时使x指向下一个参数
int y=va_arg(x,int);
if(y>m)m=y;
}
va_end(x);//清除变量x
return m;
}

int main()
{
printf("%d,%d",max(3,5,56),max(6,0,4,32,45,533));
return 0;
}

时间: 2024-11-02 16:49:56

参数-C 关于printf() 我真的很想问的一个问题!!!!的相关文章

“智能空中机器人”是个噱头么?我真的很想买,真的贵了!

摘要: 今天朋友圈被一个新上线的小玩意儿刷屏了,我很好奇这货刚上线PR咋能做的这么到位?扫了眼发现是一台智能空中机器人(就是一台用 手机 控制的四轴飞行器),可能因为本身名字起 今天朋友圈被一个新上线的小玩意儿刷屏了,我很好奇这货刚上线PR咋能做的这么到位?扫了眼发现是一台"智能空中机器人"(就是一台用 手机 控制的四轴飞行器),可能因为本身名字起的狂酷叼炸天了,所以被我朋友圈里的一帮Geek给刷屏了吧.我也很好奇这么个新鲜玩意儿到底有多酷炫,我虽然不是航模专业玩家,不敢妄加评论,但猫

想做个很简单的服务器,但是不知道怎么做了,求指点,真的很简单

问题描述 想做个很简单的服务器,但是不知道怎么做了,求指点,真的很简单 就是c/s模型的服务器端,客户端在安卓手机上,通过URL请求服务器数据,服务器返回一串json数组就好.这个功能的服务器该看什么方面的东西??完全没做过,求大牛. 解决方案 最简单的,服务器用jsp写一个web service,客户端用httpclient连它.具体google下. 解决方案二: 参考:http://blog.csdn.net/ice343241993/article/details/22037829http

LastPass想让你把密码和二次验证码存在一块,但这真的很不安全

本文讲的是LastPass想让你把密码和二次验证码存在一块,但这真的很不安全, 密码管理器LastPass最近推出了一个新功能,支持存放二次验证码/双因素验证因子.对于黑客来说,这可能是个好消息. 近年来数据泄漏事件频发,越来越多人开始使用双因素验证,来保护个人账号不受攻击者觊觎,以及检查是否有人试图登录. 一般情况下,当你要登录某个账号时,网站会将发送一次性验证码到你的设备上(通常是手机),并要求填写验证码才能继续. Google.Facebook.Dropbox在内的许多公司也在使用另一种方

ado-_bstr_t,很想知道这个类型是怎么打印出来的

问题描述 _bstr_t,很想知道这个类型是怎么打印出来的 printf((_bstr_t)(m_pRec->Fields->GetItem((long)i)->GetName()));printf(""""var); 打印语句的格式是这样的,那上面这句是怎么打印出来的?它怎么可以直接打印出来? 解决方案 先转化成BSTR 然后在转换到unicode和ansi字符串转换 解决方案二: 如果没有指定输出格式就直接输出就好了 没有问题的 解决方案三:

求大神帮忙解决 Android项目java空指针异常问题 真的很急 - -

问题描述 求大神帮忙解决 Android项目java空指针异常问题 真的很急 - - 新手小白参考网上教程学习的socket使用,代码几乎雷同老师写的就可以运行我的就会出问题,connect()方法正确可用,但是send()方法不能用,会提示如图空指针异常,但是我真的找不到是哪里的问题,求大神指点.困扰两天了 茶不思饭不想.(由于提问字数问题导包部分代码没有粘过来) 我用Broadcast在一个activity中监听到操作后广播消息过来然后触发java类里面的方法,触发到connect()就可以

HTTP真的很简单(转)

原文:HTTP Made Really Easy因为我本身网络基础就很差,所以看到这篇文章一方面是学习网络知识,另一方面为了锻炼我蹩脚的英语水平,文中如有错误,欢迎浏览指正! 前言 在看这篇文章的时候,推荐使用chrome浏览器查看http请求过程中的相关参数.chrome浏览器,可以通过'alt+cmd+i'进入开发者模式.进入'Network'一栏,在'Name'栏内找到请求的网址.查看Headers一栏,就可以看到'Response Headers'和'Request Headers'.并

对象-这条android java语句真的很复杂,求解析

问题描述 这条android java语句真的很复杂,求解析 tripListView.setOnItemClickListener(new OnItemClickListener() { public void onItemClick(AdapterView<?> arg0, View arg1,int position, long id) {Toast.makeText(ListViewExample2.this,"您选择的是" + list.get(position)

php5-wordpress好在哪里?感觉功能很简单,它真的很有技术含量吗?

问题描述 wordpress好在哪里?感觉功能很简单,它真的很有技术含量吗? 我不明白wordpress好在哪,小小的体积感觉工程量不大,功能又太少,为什么这么流行,它很有技术含量吗?为什么没人开发一个比它好的. 解决方案 Wordpress主要是可以迅速开发一个属于你自己的个人网站. 它支持的插件很多,很容易扩展,有全世界的技术人员在开发维护各种新功能. 安装,使用也简单. 你要想自己再做一个,首先推广就不容易,其次,那么多已有功能你怎么吸引开发者转过来移植到你的平台.

你们是不是真的很缺大数据工程师?

00 缘起 之所以有这个话题,是因为周末加班中午吃饭与一个同行朋友聊起了这个话题,之后再细细地结合一些其他接触的东西,确实是有些感触的. 并且对于行业的一些现状,也的确有些自己的看法,对不对先不论,这玩意儿也没有对错之分,每个人都有自己想法,当然也包括我博客虫了. 所以,有些东西.有些想法我还是愿意分享出来的,畅所欲言吧~~ 01 我眼中的大数据现状! 其实个人在大数据在大数据这个坑中,细细算来,时间也有3+年了,从一开始做大数据中心平台开发构建,到现在关注的数据上层应用挖掘.所以,基本上从数据