1.const 的全面理解:
(1)说说你对const 的理解(主要C语言范围内)
const是一个C中类型修饰符;
常见的类型修饰符有:short,long,unsigned,signed,static,auto,extern,register,volatile;
定义一个变量:类型描述符 变量名;
类型描述符包括:类型的修饰符以及数据类型 int char float ......
1)类型描述符中如果有多个关键字,它们出现的位置不影响他对变量的限制:
short int i;
int short i;
static int short i;
int static short i;
(2)下面的声明都是什么意思?
const int a
int const a
以上完全一样,描述的都是一个const的整型变量。
const int *a
int* const a
int const* const a
对指针变量类型的理解:
1). [] () * 在数据定义时与在表达式中优先级一样的理解。例如:
int *a[10] //因为 [] 的优先级 高于* ,因此是一个数组,每个成员类型为指针,指向int
int (*a)[10] //因为()的优先级高于[] ,因此,先看里面,是一个指针,指向的类型为一个数组
2). 指针的判断从右向左:
const int *a //a是变量名,*表示它是一个指针(类型已经确定),余下的是指向的类型;
//因此,a是一个指向const int 的指针,即指向的数据不可修改;
int* const a // *const一起来修饰a,即a只读,*表示a是一个指针,因此,这是一个只读指针,指向的类型为int型 // 的变量
int const *const a // *表示指针,因此指针不可修改,int const是指针指向的类型,仍然是const;
(3)
typedef void* VP;
(a)const void *ptr存储位置;
(b)const VP ptr存储位置;
首先要理解typedef是定义一种数据类型,一定要与define区分开;
typedef void* VP; // VP是名字,余下的是这个类型的真实类型
const VP ptr; // 是不是替换为const void *ptr;??不是,void*是一个整体
// const int i; == int const i;
// VP const ptr; 即 void *const ptr;
(4)为什么还在编程中全用const?
1).向其他程序员传递一个信息。这个不要修改。
2).有可能让编译器产生更精简紧凑代码,减少bug。
3).合理的保护我们只读的数据,避免不必要的错误。
使用位置:
1)定义常量,防止被修改;
2)函数的参数中,如果不期望子函数去修改被调用函数的某个数据,可以加以限制。例如:
char *strcpy(char *dest , const char *src);
char *strcpy(char *dest,const char *src,size_tn);
3) 在C++中,类的成员函数的使用。
=======================================================================================
2. sizeof 是函数吗?准确的列出sizeof() 的功能。以下代码中(32位平台):
int a[10];
int *ptr;
以下内容作为右值时,是否正确,如果正确,值为多少?
sizeof(a)
sizeof(a[10])
sizeof(a[1])
sizeof(ptr)
sizeof(*ptr)
sizeof(int)*ptr
(1)谈谈你对sizeof 的理解。
sizeof不是函数,C语言的一个关键字,作为右值时,求某个数据类型(sizeof(int))或某个变量对应的数据类型sizeof(a)来定义某个变量时,在当前平台下所需要占用内存空间的大小。并不是真正求某个变量本身的内存空间大小,也不会涉及到对这个空间的访问。
sizeof(a) // 找到a的类型,int[10]是a 的类型,因此是一个数组,相当于sizeof(int[10]),值40(32位平台)
sizeof(a[10]) // a[10]本身是一个越界访问,但是,这里并不是去访问a[10]的空间大小,而是求它的类型
// a[10] ----> *(a+10) 即a指向的类型,即int型,因此,求的是sizeof(int)即4个字节。
sizeof(a[1]) // 同上,4字节。
sizeof(ptr) // 指针本身类型占用空间大小,32位平台4个字节。
sizeof(*ptr) // ptr指向的数据类型,因此为int型,4个字节。
sizeof(int)*ptr // 编译出错的。sizeof(int), *ptr取内容, 中间没有运算符。
=======================================================================================3.static 的理解
#include
int counter(int i){
static int count = 0;
count = count + i;
return(count);
}
main(){
int i,j;
for(i=0;i<=5;i++)
{
j=counter(i);
printf("i:%d\n,j:%d\n,i,j");
}
}
(1)列出所有你对static的理解。
(2)谈谈你对static的理解(C部分,或者C++部分)。
解题思路:
static定义的数据存放的区域,怎么初始化?以及它的生存周期和作用域的问题。
本题中,static所在行定义一个静态的局部变量(已经初始化),值存放在数据段中,生存周期是从程序运行到程序结束。
参数 int i 这一行,定义一个普通的变量,存储类型实际为auto,因此,每进入一次这个函数,重新定义这个变量,退出这个函数,这个变量的空间释放掉。
关于static的理解。首先明确数据的存储类型和可执行文件的段域问题(具体可查阅C部分关于存储问题的资料)
1)定义一个静态的变量。对应要理解auto存储类型。初始化,生存周期,作用域。
static int i =10; // 局部或者全局
2)定义一个函数的时候。在当前的文件中可以访问,这个函数作用域为当前文件(模块)。
static int fun();
3)C++中,类的成员定义时,有静态成员变量和静态成员函数。
class A
{
private:
static int s_value;
};
int A :: s_value = 0; //初始化
这个成员不属于类的对象,而属于类。对它的访问,全用类。例如 A :: s_value。
静态成员函数:
class A
{
private:
static void func(int value);
};
强调一点: 同样是属于这个类,只能访问类的静态的成员变量,不能访问对象的其他数据。
如果在头文件中定义了一个静态变量,因为静态变量只属于某个文件,如果多个.c 的文件包含了这个头文件,实际上相当于定义了多个静态成员变量(每个文件一个)
如果在头文件中定义一个全局变量,如果被多个.c 的文件包含的话,要这样用:
在*.h中
extern int g_value; //注意,不要初始化值!
然后各个.c 的文件包含,同时在某个.c 的文件初始化。
=======================================================================================
4.volatile的全面理解
#include
#inc;ude
#include
static jmp_bufbuf;
main()
{
int a;
volatile int b;
a=2;
b=3;
if(setjmp(buf)!=0)
{
printf("a:%d,b%d\n",a,b);
exit(0);
}
a=5;
b=5;
longjmp(buf,1);
}
gcc -o volatile volatile.c -O3
使用优化编译后,输出的结果是什么?
(1)谈谈你对volatile的理解。
(2)volatile可以应用到哪些地方。
考点分析:
(1)对setjmp和longjmp的理解。
(2)对编译优化的理解以及对volatile的理解。
解题思路:
int setjmp(jmp_bufenv);
void longjmp(jmp_bufenv,int val);
用于跳转,setjump设置一个跳转栈位置,longjmp执行跳转到最近一个setjmp位置。
volatile到底用在哪些地方?volatile到底表示什么意思?
表示这个变量时易变的。实际是要求编译器每次直接读取原始的内存址而去掉所有的优化。
在嵌入式开发的寄存器数据定义时经常使用。
#define CONDATA *((volatile int *)0x80000000)
volatile的应用位置:
1)硬件寄存器数据访问时,如果这个寄存器的数据有可能被硬件修改。一定使用volatile来定义这个变量。
2)中断服务程序中一些非自动变量。
3)在多线程中被几个线程共享的数据。
其他问题:
1)一个参数既可以是const还可以是volatile吗?解释为什么。
2)一个指针可以是volatile吗?解释为什么。
3)下面的函数有什么错误:
int square(volatile int *ptr)
{
return *ptr **ptr;
}
=======================================================================================
5.数据类型限制
(1)double和float的精度分别是?float变量与零值比较。
(2)请问下面程序有什么错误?如何改正?
#define Max_CB 500
void LmiQueryCSmd(Struct MSgCB *pmsg)
{
unsigned char ucCmdNum; //unsigned char 范围是0~255,不可能超过500,所以for循环是一个死循环
......
for(ucCmdNum = 0;ucCmdNum
(3)0 的理解
评价下面代码片段是否正确:
unsigned int zero = 0;
unsigned int compzero = 0xFFFF;
/*1 's complement of zero*/
相关题目:
(1)详细阐述浮点型数据在计算机中的存放方式。
考点分析:
(1)C语言的基础知识。数据类型的限制。
(2)是否深究技术细节。
解题思路:
首先要理解在任何平台下,任何数据类型都是有范围限制。在Linux平台限制的文件是:
limits.h(限制与整型相关的数据类型的范围)
unsigned int 型与当前的平台相关0~2^32-1
int -2^31~2^31-1
float.h(限制与浮点型相关的数据类型的范围)。find/usr/-name float.h
(1)double和float的精度分别是?float变量与零值比较。
(a)没有unsigned float 和 signed float的用法;
(b)表示范围由指数位决定;
(c)有效位由尾数有效值数值位决定。
float 23bit:最大为2^23转换成十进制最多有7位有效位,但只能保证6位有效位。
double 同理,15~16(十进制)个有效精度。
float f;
if(f != 0) //不可以的
#define EPSINON 0.00001 //定义一个宏
if ((f >= -EPSINON) && (f <= EPSINON))
=======================================================================================
(1)
int i=3;
int j=(++i)+(++i)+(++i); // ( 5 + 5 )+6
int k=(i++)+(i++)+(i++);
求i,j,k的值。
i:6; j:16; k:9;
(++i) + (++i)中的++完成后,“+”运算符已经可以执行,因此立即执行。因此,所谓的++在前,先执行++,再执行其他运算是在一个表达式内这样理解。并不需要到语句的结束。
而++在后面,整个语句结束后再执行++操作。
(2)下面的结构是合法的吗?如果是它做些什么?
int a=5,b=7,c;
c=a++ +b; //贪心法:一个变量期望尽可能多的关联运算符。
求a,b,c的值。
a:6; b:7; c:12
(3)自加操作(++)
main()
{
int i=3;
int j;
j=sizeof(++i+++i); //不加空格会是什么情况;
printf("i=%d j=%d",i,j);
}
这段程序的输出是?
i:3; m:4;
在这里sizeof 求的是对应类型,并不会执行相应的运算。
另外,++i++i出错的原因?
因为贪心算法,++i+++i 理解为++i++ +i,即:
++i++理解为:++i = i++,++i为左值是不允许的,编译出错。
考点分析:
(1)C语言的基础知识。编译环境的熟悉。
(2)是否深究技术细节。
解题思路:
++/-- 在变量前和变量后区别很大:
在前面:++a,先执行++(执行到下一个操作符可以完成操作执行时),再执行其他操作;编译器的约定需要关注。
在后面:a++,先执行其他操作,在执行++。
=======================================================================================
7.逻辑运算符的短路问题
int i=1;
int j=0;
if((i++>0) || (++j>0)) //i++ = 1结果为真了,不会继续判断,输出时 i++ =2,j =0;
;
printf("i:%d,j:%d\n",i,j);
i:2; j:0;
考点分析:(1)C语言基础知识。编译环境的熟悉。
(2)是否深究技术细节。
解题思路:
遇到这个题目不要考虑得太简单,一个面试题一定有考察的地方。
逻辑与 A&&B
逻辑或 A||B
=======================================================================================