C语言面试(二)

版权声明: https://blog.csdn.net/qq_41880190/article/details/80414918

数据存储与变量

变量的声明与定义

例如如下程序会不会报错?为什么?

#include<stdio.h>
static int a;
static int b[];
int main(int argc,char *argv[])
{
    printf("%d %d\n",a,b[0]);
    return 0;
}
static int a = 8;
static int b[4];

这个程序是不会报错的,并且连警告都不会出现。输出结果:8 0

 static int a ,这句程序是声明全局变量a;static int b[],这句程序是声明全局数组变量b,并且是不完全声明,也
就是可以省略数组下标。static int a = 8,这里才是定义全局变量a,static int b[4],这里是定义全局变量b。
局部变量与全局变量的较量 
请问如下程序所示输出什么?
局部变量与全局变量


#include<stdio.h>
static int a = 8 ;
int main( int argc , char *argv[] )
{
    int a = 4 ;
    printf( "%d \n" , a ) ;
    return 0 ;
} 
C语言规定,局部变量在自己的可见范围内会“挡住”同名的全局变量,让同名的全局变量临时不可见。即在局部变量的可见范围内不能访问同名的全局变量。因此本程序输出为:4。
char、int、float、double的数据存储 
请问如下程序,i和j输出什么?
数据存储
float i = 3 ;
int   j = *(int*)(&i) ;
printf( "i = %f \n" , i ) ;
printf( "j = %#x \n" , j ) ;

i是毋庸置疑是:3.000000。但是j呢?3.000000?答案是否定的,j是输出:0x4040 0000。有人会问了,难道j是随机输出?瞎说,j输出0x4040 0000是有依据,是一个定值!

由于i是float数据类型,而j是int数据类型。理论上说,j是取了i的地址然后再去地址,应该得到的就是i的值:3。

但是问题的关键就是float数据类型的存储方式和int数据类型不一样,float是占用4个字节(32位),但是float存储是使用科学计数法存储,最高位是存储数符(负数的数符是0,正数的数符是1);接下来8位是存储阶码;剩下的23位是存储尾数。上面i=3.000000,那么3.000000(10进制) = 11。

数据在电脑中存储都是二进制,这个应该都没有疑问。那么这里的数符为:0 ,阶码为:E – 127 = 1 ,那么阶码为:E = 128 即为:1000 0000 (2进制) ,尾数为:100 0000 0000 0000 0000 0000 。那么存储形式就是:0100 0000  0100 0000 0000 0000 0000 0000。这个数据转换成16进制就是0x4040 0000。

数据存储方式
char、int、float、double的存储方式如下:
提问:如果i = -3.5 的话,请问j输出多少?
i = -3.500000
j = 0xc0600000
容易忽略char的范围 
如程序清单2. 5所示,假设&b=0x12ff54,请问三个输出分别为多少?
unsigned int b = 0x12ff60 ;
printf("( (int)(&b)+1 )         = %#x \n" , ( (int)(&b)+1 )           ) ;
printf("*( (int*)( (int)(&b)+1 ) )  = %#x \n" , *( (int*)( (int)(&b)+1 ) )   ) ;
printf("*( (char*)( (int)(&b)+1 ) ) = %#x \n" , *( (char*)( (int)(&b)+1 ) )  ) ;
很显然,&b是取无符号整型b变量的地址,那么(int)(&b)是强制转换为整型变量,那么加1即为0x12ff54+1=0x12ff55。所以( (int)(&b)+1 )是0x12ff55。
指针加1取字符型数据
由于( (int)(&b)+1 )是整型数据类型,通过(int *)( (int)(&b)+1 )转化为了整型指针类型,说明要占4个字节,即为:0x12ff55、0x12ff56、0x12ff57、0x12ff58,再去地址*( (int *)( (int) (&b)+1 ) )得到存储在这4个字节中的数据。但是很遗憾,0x12ff58我们并不知道存储的是什么,所以我们只能写出0x**0012ff。**表示存储在0x12ff58中的数据。如图2. 2所示。
指针加1取整型数据
以此类推,*( (char *)( (int) (&b)+1 ) ) = 0xff。如图2. 3所示。
但是,*( (char *)( (int) (&b)+1 ) )输出的却是:0xff ff ff ff !
问题出现了,为什么*( (char *)( (int) (&b)+1 ) )不是0xff,而是0xff ff ff ff?char型数据应该占用1个字节,为什么会输出0xff ff ff ff?
使用%d输出,
printf("*( (char*)( (int)(&b)+1 ) ) = %d \n" , *( (char*)( (int)(&b)+1 ) ) ) ;
结果为-1???
问题出在signed char 的范围是:-128~127,这样肯定无法储存0xff,出现溢出。所以将
printf("*( (char*)( (int)(&b)+1 ) ) = %#x \n" , *( (char*)( (int)(&b)+1 ) ) ) ;
 f("*( (unsigned char*)( (int)(&b)+1 ) ) = %#x \n" , 
*( (unsigned char*)( (int)(&b)+1 ) ) ) ;
就可以输出0xff,因为unsigned char 的范围是:0~255(0xff)。

阅读更多 登录后自动展开
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页