C语言面试(二)
程序员文章站
2022-07-08 14:54:06
...
数据存储与变量
变量的声明与定义
例如如下程序会不会报错?为什么?
#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)。