printf函数的细节问题探索

来源:互联网 发布:淘宝买口服催情药 编辑:程序博客网 时间:2024/06/14 07:08


在C语言的学习中,最先学习的,也是大家最熟悉的肯定就是printf函数了,今天来给大家来说一下printf函数的一些细节问题。


代码:

 

char arr[2][3] = {'a','b','c','d','e','f'};<span style="color:#FF0000;">int *p = arr;</span>int i;for(i=0;i<6;i++){printf("%x\t%c\t%p\n",*(p+i),*(p+i),p+i);}

大家想一下,一个指向整型数据的一维指针,可以来存放字符型二维数组的地址吗?

编译过后我们发现,只是出现了一个警告

警告:从不兼容的指针类型初始化怎么来消除这个警告呢?只需要改动一点点就行了int *p = (int *)arr

这个只是一个小问题,接下来我们就要来打印出来了哦,大家想一下,我们打印出来的第一行应该是怎样的数据呢?

我们来单独打印出来看看,会出现什么结果呢?

printf("%c",*(p+0));
这个会出现什么结果呢?乱码?还是a?还是直接打出来abcd?或者dcba?

一切以结果为准,编译执行过后,我们发现

结果:a

按照这个想法,那么我们再用整型输出看看

printf("%d\n",*(p+0));
我们当然会想当然地会输出97,因为字符输出是a嘛

但是,大家会发现,出错了,结果是1684234849对吧。大家想一下是为什么会出现这种问题呢?

----------分隔线--------------------------------

最后揭谜底了

我们在强制类型转换的时候,原来我们把殖民地arr[0]相近的几个元素一“合成”了一个整型数据,这是什么意思呢?

由于p是一个指向整型数据的指针,所以*(p+0)占4个字节,那么我们printf("%d",*(p+0));是哪4个字节的数据呢?原来就是把我们的arr[0],arr[1],arr[2],arr[3]当成了一个整型数据输出来,那么为什么我们用printf("%c",*(p+0));能打印出来a呢?这,就要说到我们的另外一个问题了


当我们使用printf的时候,我们关心得最多的就是引号后面的东西,其实引号里面也是有讲究的,当我们用"%d",输出的时候,我们就按照十进制输出到屏幕而如果我们用"%c"时呢,就会按照字符型输出到屏幕

但是,当我们用"%c"输出时,这是我们只能向屏幕输出1个字节的数据,如果我们的输出参数一个4个字节的整型数据,那么我们就会只取低8位的数据来输出,所以我们用整型数据输出的时候会出现一个我们不认识的乱码,而我们用字符型输出能输出我们想看到的a

最后再说一句,其实1684234849这个数字也不是什么乱码,如果我们化成十六进制我们就会发现其实它是0x646362610x61其实就是a的ascii码


再来多说一个关于数据整合的问题,在我们的对底层的操作的时候,经常会遇到数据的整合,那么这个原理是什么样的呢?其实这是很简单的一个问题,我们来慢慢说。

我们来举一个例子,

十进制数:15

十六进制数:0x0e

二进制数:0000 1111

有些人可能学会了十六进制转化二进制过后,会把十进制转化二进制搞混淆,会认为就是把5的二进制和1的二进制组合起来就是了,即:0001 0101,这显然是不对的。来举一个实例吧!

char carr[2] = {'a','b'};short *p = carr;printf("%d\n",*p);pirntf("%x\n",*p);
大家看,这个简单的程序,我们把carr的地址存放在一个指向短整型的指针里面, 我们来看看结果

251856261
这个是结果为什么会出现这种情况前面已经说了,现在我们来看看这个存储的原理

我们的程序存储carr 时是存的'a'和'b'的ascii码,十进制就是97和98,而我们存储'a'和'b'时是连续存储的,所以我们还要转化成二进制来进行计算,97的二进制是0110 0001,98的二进制是0110 0010,再来整合,记住计算机的大端小端,我们的电脑的98在前,97在后,即为:0110 0010 0110 0001,这个二进制数计算下来就是我们的25185,这就是计算机来处理数据时的过程,而我们的十六进制就简单了,我们知道,每4个二进制数就能合成一个十六进制数,所以自然就是0x6261了。

0 0
原创粉丝点击