char数组和十六进制格式化sprintf

char ch[2];

sprintf(ch, "%x", 100);
printf("字符串%%s输出:%s\n", ch);
printf("字符%%c输出ch:%c\n", ch);
printf("字符%%c输出ch[0]:%c\n", ch[0]);
printf("字符%%c输出ch[1]:%c\n", ch[1]);
printf("十六进制%%x输出ch:%x\n", ch);
printf("十六进制%%x输出ch[0]:%x\n", ch[0]);
printf("十六进制%%x输出ch[1]:%x\n", ch[1]);
printf("十进制%%d输出ch:%d\n", ch);
printf("十进制%%d输出ch[0]:%d\n", ch[0]);
printf("十进制%%d输出ch[1]:%d\n", ch[1]);

输出:
字符串%s输出:64
字符%c输出ch:>
字符%c输出ch[0]:6
字符%c输出ch[1]:4
十六进制%x输出ch:22ff3e
十六进制%x输出ch[0]:36
十六进制%x输出ch[1]:34
十进制%d输出ch:2293566
十进制%d输出ch[0]:54
十进制%d输出ch[1]:52

说明:
int sprintf( char *buffer, const char *format, [ argument] … );
sprintf指的是字符串格式化命令,主要功能是把格式化的数据写入某个字符串中。
100十六进制为64,ch中存入'6''4',以%c字符输出时ch[0]='6',ch[1]='4'
以%d十进制数输出时,对应这两个字符的ACSII码为 54 52
同理,%x十六进制输出时,对应54 52的十六进制36 34

printf("字符%%c输出ch:%c\n", ch);
printf("十六进制%%x输出ch:%x\n", ch);
printf("十进制%%d输出ch:%d\n", ch);
这两个输出的结果是不好理解的,刚开始以为是由高位54低位52组成的一个十六位数,测试了多次结果都不对,后来在VS里面测试发现这个结果每次都是变化的,才想到这是指针,也就是ch的地址。
char[]是“特殊的”数组,是由char组成的字符串,数组名代表地址,也是指向存放该数组的地址的指针。对于数组名,当以%s输出时,就将各个字符以整体字符串的形式输出,以数字的形式(包括%c %d %x)时,输出地址,而%c是1个字节,地址是4个字节,所以地址被截取为1个字节后输出,将4个字节的int类型截取为1个字节char类型,测试后%d会输出63,对应ASCII为'?'

PS:发现Linux和Windows的编译器区别,GCC中同一程序多次运行时变量地址保持不变,而在VS中每次都会变化。

 


sprintf 是个变参函数。

可变参数函数顾名思义,就是函数参数个数是未知的是可变的。sprintf中[ argument]的参数和format中的格式化符号一一对应。

 

sprintf 对于写入buffer的字符数是没有限制的,这就存在了buffer溢出的可能性。

例如:

char buffer[2];
sprintf(buffer, "%x", 1000);
printf("格式化后buffer:%s\n长度:%d\n", buffer, strlen(buffer));

输出:
格式化后buffer:3e8
长度:3

说明:
首先定义一个长度为2的char数组buffer,然后使用sprintf将1000以十六进制存入buffer,1000十六进制为3e8,所有buffer长度变为3,发生溢出。

 

4字节“暴力”截取1字节

union A
{
	int i;
	char c;
};
union A a;
a.i=2293567;
printf("截取后:十进制%d,字符%c\n", a.c, a.c);

输出:
截取后:十进制63,字符?

  • 3
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值