一、static有什么用途?
答:1.隐藏
未加static全局变量和函数都具有全局可见性,其他源文件也能访问。若加上static就会对其他源文件隐藏,这样可以在不同的文件中定义同名函数和同名变量,不必担心命名冲突;对函数来讲,仅限于隐藏,而对于变量,还有以下两个作用。
2.保持变量的内容持久
存储在静态数据区的变量会在程序刚开始运行时就完成初始化,也是唯一的一次初始化。共有两种变量存储在静态存储区:全局变量和static变量,只不过和全局变量比起来,static可以控制变量的可见范围,说到底static还是用来隐藏。
3.默认初始化为0
其实全局变量也具备这一属性,因为全局变量也存储在静态数据区。在静态数据区,内存中所有的字节默认值都是0x00。
最后对static的三条作用做一句总结:
首先static的最主要功能是隐藏,其次static变量存放在静态存储区,所有它具备持久性和默认值0。
二、static全局变量与普通的全局变量有什么区别?
static局部变量和普通局部变量有什么区别?
static函数与普通函数有什么区别?
答:1. static全局变量与普通的全局变量有什么区别:
static全局变量在静态存储区中,静态存储区在整个程序运行期间都存在;未初始化的全局静态变量被程序自动初始化为0;全局静态变量在声明它的文件内可见,作用域从定义之处开始到文件结尾;在声明它的文件外不可见,不可被修改,可以定义相同名字的变量,不会发生冲突。
普通的全局变量也是在静态存储区中,在声明它的文件之外可见;全局变量默认初始化为0;
普通的全局变量的作用域是整个源程序, 当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。
2. static局部变量和普通局部变量有什么区别:
局部变量加上关键字static就被定义为局部静态变量;
内存位置:局部静态变量在静态存储区,普通局部变量在栈中;
初始化:局部静态变量初始化为0,未初始化的局部变量值不定;
作用域:局部静态变量仍为局部作用域,当定义它的函数或语句块结束时,作用域也随之结束;但是局部静态变量在离开作用域之后,并没有被销毁,而是仍然驻留在内存中,直到程序结束,只不过不能再对他们访问。普通局部变量的作用域是定义它函数或语句块,函数或语句块结束,作用域也随之结束。
局部静态变量可以保存上次运行的结果,具有统计次数的功能,可以作为一个计数器。
3. static函数与普通函数有什么区别:
在函数的返回类型前加上关键字static,函数被定义成静态函数。
函数的定义和声明默认情况下是extern的,但静态函数只是在声明它的文件当中可见,不能被其他文件使用,其他文件可以定义相同名字的函数,不会发生冲突;普通函数可以被其他文件使用。
另外:
存储说明符auto,register,extern,static,对应两种存储期:自动存储期和静态存储期。
auto和register对应自动存储期。具有自动存储期的变量在进入声明该变量的程序块时被建立,它在该程序块活动时存在,退出该程序块时撤销。
关键字extern和static用来说明具有静态存储期的变量和函数。用static声明的局部变量具有静态存储持续期(static storage duration),或静态范围(static extent)。虽然他的值在函数调用之间保持有效,但是其名字的可视性仍限制在其局部域内。静态局部对象在程序执行到该对象的声明处时被首次初始化。
三、下面几个定义有何区别?
char * const p; //const修饰p,const p是char *类型,p指针不可修改,为只读,
//但指向的内存单元的内容可修改(p is a const pointer to char);
char const * p; //与const char *p;一样
const char *p; //原文: p is a pointer to const char;
//与char const * p; 一样,const修饰char,p指向的内存单元的内容不可以修改,
//但p指针可以被修改
const char * const p; //则指针变量的值和指针指向的内存单元的值均不可修改
理解记忆:
1、关键是const修饰谁
2、由于没有const *的运算,const实际是修饰前面的。
(1)char *p:p是一个工作指针,可以用来对任意位置 (非系统敏感区域)进 行读操作和写操作 ,一次读写一个字节(char占一个字节)。
(2)const char*p或者char const *p(因为没有const*p运算,因此const修饰的还是前面的char):可以对任意位置(非系统敏感区域)进行“只读” 操作。(“只读”是相对于char *p来说所限定的内容)
(3)char *const p(const 修饰的是p):只能对“某个固定的位置” 进 行读写操作,并且在定义p时就必须初始化(因为在后面不能执行“p=..”的操作,因此就不能在后面初始化,因此只能在定义时初始化)。(“某个固定的位 置”是相对于char *p来说所限定的内容)
(4)const char **p或者char const**p :涉及两个指针p和 *p。由于const修饰char ,对指针p没有任何限定,对指针*p进行了上面情况(2)的限定。
(5)char *const *p:涉及两个指针p和 *p。由于const修饰前面的char*,也就是对p所指向的内容*p进行了限定(也属于前面的情况(2))。而对*p来说,由于不能通过"*p=..."来进行另外赋值,因此属于前面的情况(3)的限定。
(6)char **const p : 涉及两个指针p和 *p,const修饰p,对p进行上面情况(3)的限定,而对*p,没有任何限定。
四、关键字const有什么含意?
答:声明“只读”变量,可以修饰函数参数、函数返回值和变量。
1.关键字const的作用是为给读代码的人传达非常有用的信息,实际上,声明一个参数为常量是为了告诉了用户这个参数的应用目的。
2.通过给优化器一些附加的信息,使用关键字const也许能产生更紧凑的代码。
3.合理地使用关键字const可以使编译器很自然地保护那些不希望被改变的参数,防止其被无意的代码修改。简而言之,这样可以减少bug的出现。
五、关键字volatile有什么含意?并举出不同的例子?
答:volatile变量可能被意想不到地改变,编译器就不会假设这个变量的值;精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。
volatile变量的例子:
1、并行设备的硬件寄存器(如:状态寄存器)
2、一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)
3、多线程应用中被几个任务共享的变量
延伸:
1、一个参数既可以是const还可以是volatile吗?解释为什么。
可以。比如只读的状态寄存器,它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。
2、一个指针可以是volatile 吗?解释为什么。
是的。尽管这并不很常见,一个例子是当一个中服务子程序修该一个指向buffer的指针时。
3、下面的函数有什么错误:
int square(volatile int *ptr)
{
return *ptr * *ptr;
}
ptr指向一个volatile型参数,*ptr的值可能被意想不到地该变,有可能不是返回的所期望的平方值。
六、局部变量能否和全局变量重名?
局部变量可以和全局变量同名。
七、如何引用一个已经定义过的全局变量?
答:用extern关键字,声明这个全局变量然后可以使用,这个全局变量在别的文件内已定义;
用包含头文件的方式,在头文件中用extern声明,在一个源文件中定义,这样通过包含头文件的方式可以使用这个全局变量。
八、全局变量可不可以定义在可被多个.C文件包含的头文件中?为什么?
答:不可以。因为每个.c文件引用该.h文件时,会对.h中的函数重新定义一次。
如果全局变量被定义在可被多个.c文件包含的头文件中时,就会出现重复定义。
所以,应该是在某个.c文件里面定义,在.h中用extern进行声明。
延伸:
在多个源文件中,用static声明同名的全局变量,定义为静态全局变量;
而只有一个文件对这个静态全局变量初始化,在连接时不会报错。
九、说说堆与栈的区别?
答:栈:存放局部变量,每次函数调用时需要保存的信息(参数值,返回地址,环境信息);
堆:存放用malloc等函数开辟的内存空间,由程序员分配和释放;
十、寄存器变量可不可以访问其地址?可否是全局变量?在什么场合使用寄存器变量?
答:寄存器变量使用CPU中的寄存器,寄存器变量没有地址,不能用“&”运算符求其地址;
与编译器有关,最好不要将全局变量声明为寄存器变量;
循环控制变量常使用寄存器变量,寄存器变量适用于使用频繁且访问速度较高的变量。
十一、包含预定义头文件< > 和" "的区别?
答:<>:系统到标准库中查找头文件
“” :系统先到本地库查找,若没有在到标准库查找
十二、举例说明typedef和define的用法。
答:
typedef:构造"新的"数据类型,相当于给现有的数据类型起别名;
typedef struct node
{
int data;
struct node *next;
}Node;
typedef unsigned int u_int32;
define : 定义常量
#define PI 3.14
#define EPSINON 0.000001
十三、do……while和while……do有什么区别?
答:do…while:是先循环一次,再做判断;
while….do:是先做判断,若为真,再循环。
十四、语句for( ;1 ;)有什么问题?它是什么意思?
答:for(; 1; )与while(1)功能相同,会不停地循环,很有可能出现死循环。
十五、分别写出bool、int和float类型变量与“零值”比较的if语句。
bool flag:
if(flag) 或 if(!flag)
int num;
if(num == 0) 或 if(num != 0)
float num;
const float EPSINON = 0.000001;
if((num >= -EPSINON) && (num <= EPSINON))
延伸:
char *p与“零值”比较的if语句:
if(p == NULL) 或 if(p != NULL)
十六、请写出下列代码的输出内容
#include<stdio.h>
main()
{
int a,b,c,d;
a=10;
b=a++;
c=++a;
d=10*a++;
printf("b,c,d:%d,%d,%d",b,c,d);
return 0;
}
输出:b, c, d : 10, 12, 120
十七、设有以下说明和定义:
typedef union {long i; int k[5]; char c;} DATE; struct data { int cat; DATE cow; double dog;} too; DATE max; 如果long,double类型占8字节,int类型占4字节,char类型占8字节,则语句 printf("%d",sizeof(struct date)+sizeof(max));的执行结果是:
答案未定
十八、请找出下面代码中的所以错误
说明:以下代码是把一个字符串倒序,如“abcd”倒序后变为“dcba”
include"string.h"
main()
{
char*src="hello,world";
char* dest=NULL;
int len=strlen(src);
dest=(char*)malloc(len);
char* d=dest;
char* s=src[len];
while(len--!=0)
d++=s--;
printf("%s",dest);
return 0;
}
正确完整代码:
#include<string.h>
#include<stdlib.h>
int main()
{
char *src = "hello,world";
char *dest = NULL;
int len =strlen(src);
dest = (char *)malloc(sizeof(src));
memset(dest,'\0',sizeof(src));
char *d =dest;
char *s = src + len -1;
while(len-- != 0)
*d++ = *s--;
*d = '\0';
printf("%s\n",dest);
free(dest);
return 0;
}
十九、用宏定义写出swap(x,y),交换两个变量的值:
#define swap(x, y) \
x = x + y;\
y = x - y;\
x = x - y;
二十、下面语句有何错误:
char* s="AAA";
printf("%s",s);
s[0]='B';
printf("%s",s);
答:语句s[0]='B'; 试图修改字符串,会出现段错误,"AAA"是字符串常量,存放在静态存储区中,不可修改。
二十一、一个C程序的执行是从()
A:本程序的main函数开始,到main函数结束
B:本程序文件的第一个函数开始,到本程序文件的最后一个函数结束
C:本程序的main函数开始,到本程序文件的最后一个函数结束
D:本程序文件的第一个函数开始,到本程序main函数结束
答:A
二十二、在C语言中,要求运算数必须是整型的运算符是()
A:/ B:++ C:!= D:%
答:D
二十三、C语言中,逻辑“真”等价于()
A:大于零的数
B:大于零的整数
C:非零的数
D:非零的整数
答:C
二十四、int (*s[10])(int) 表示的是什么?
答:函数指针数组。s是数组名,有10个指针元素,*s[10]是数组指针,
每个元素指向含有一个int类型参数的函数,函数返回值也是int类型。
二十五、对于一个频繁使用的短小函数,在C语言中应用什么实现,在C++中应用什么实现?
c用宏定义,c++用inline(内联函数)
浙公网安备 33010602011771号