欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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)。

C语言面试(二)C语言面试(二)C语言面试(二)