C基础面试题

1、全局变量和局部变量的应用:
局部变量会屏蔽全局变量,函数中默认使用的是局部变量,而我们可通过在变量名前添加“::”来指定访问全局变量。
全局变量可声明在可被多个.c文件包含的头文件中,但在这些同名的全局变量中只能有一个C文件对其赋值(定义)。
可以用引用头文件的方式,也可以用extern关键字来引用刚已经定义过的全局变量。
我们通过实例解析下:
Global.h

  1 #ifndef GLOBAL_H
  2 #define GLOBAL_H
  3 extern int g;
  4 #endif

这里声明了一个全局变量 g,注意,头文件只是一些接口的说明及数据的声明,一般不采用定义方式。
global1.cpp

  1 #include "Global.h"
  2 #include <stdio.h>
  3
  4 extern int g;
  5
  6 void func(int a)
  7 {
  8         a += 1;
  9         printf("%d",a);
10 }
11
12 int main()
13 {
14         func(g);
15 }

注意第4行,我们使用了extern关键字便是引用已经定义过的全局变量。

global2.cpp

  1 #include "Global.h"
  2 
  3 int g = 20;

这里讲一点:只能有一个赋值,否则出错。

编译执行结果为:21.

全局变量时存储在 全局/静态存储区,而局部变量存储在堆栈。

在这里的局部变量我们可引生出一个知识点:静态变量,使用关键字static。
通常,函数中定义的局部变量在函数作用域结束时消失,如果再调用该函数时,将重新创建该变量的存储空间,并被重新初始化。如果我们想使该变量在程序的整个生命周期内有效,即可使用static定义该变量为静态变量,其值只执行一次初始化,之后被持续保存。而又不像全局变量,static变量不同之处在于它在其作用域之外是不可用的。
static的第二层意思:在某个作用域外不可访问。
当应用static于函数名和所有函数外部的变量时,它的意思是“在文件的外部不可以使用这个名字”。所以如果在一个文件内(所有函数外部)定义变量,而在另一个文件使用extern 引用该变量时是不可行的。即将上文的global2.cpp中的g定义为 static int g = 20,则global1.cpp中不会找到g。

2、整型常量的存储
整型数据在内存中是以二进制的形式存放的,数值是以补码表示的。一个整数的补码和其原码的形式相同,一个负数的补码是将该数绝对值的二进制形式按位取反再加1.

3、整型数据的计算
float i ;
i = 5/2;// 2
两操作数类型一样才能做运算,不一样时按类型转换
float i;
i = 5.0/2; // 2.5

4、float型变量
float a与“零值”比较的if语句:
if( (a >= -0.00001) && ( a <= 0.00001 ) )

5、整数自动转换
当将一个负数赋值给无符号类型变量时,负数将自动转换为无符号类型数值,其值范围为0~65535.

6、取模 % 运算:两侧必须为整数

7、define的复合表达式

#define fun(a)( (a)*(a) )
int a = 5;
int b ;
b = fun(a++);

实际fun展开为(a++)*(a++),则得结果为b = 25,a = 7.在此a累加了两次。

8、内存越界
char *p1 = “BeanKo”;
char p2 = (char )malloc( sizeof(char) * strlen(p1) );
strcpy(p2,p1);

p1是个字符串常量,它的长度为6个字符,但实际上所占的内存大小是7个字节,即包括结束标识”\0”.
若以写法 char a[7] = {‘B’,’e’,’a’,’n’,’K’,’o’}; 则就没有结束标志符 。

可修改 :char p2 = (char )malloc( sizeof(char) * (strlen(p1) + 1) );

9、数组名作为左值和右值的区别

char a[3] ,b[] = "china";
a = b;
printf("%s",a);

你发现什么问题了么?
GCC下报错:
arrayAsValue.c:6: error: incompatible types when assigning to type ‘char[3]’ from type ‘char *’
这并不能通过编译。
当数组作为右值时,与&a[0]一样,它代表的是数组首元素的地址,而不是数组的首地址。
同样的,数组作为左值时,代表的也是数组首元素的地址,但是这个地址开始的一块内存是一个整体,只能访问数组中的某个元素而无法访问整个数组,所以可以把a【3】当成左值,而不能把a当成左值。

若将a改为 char *a, 则将b赋值给a时,表示a指向数组首元素的地址,这是一个整体。

10、const 与 #define相比有何优点
const 修饰的只读变量具有特定的类型,而宏没有数据类型。编译器可以对前者进行类型安全检查,而对后者只能进行字符替换,没有类型安全检查,并且在字符替换时可能会产生意料不到的错误。
有些集成化的调试工具可以对const常量进行调试,但不能对宏常量进行调试。
编译器通常不为普通const只读变量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的值,没有了存储与读内存的操作,使得它的效率也很高。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值