1、考点:指针加减要乘以相应单位量
错题:
unsigned char *p1;
unsigned long *p2;
p1 = (unsigned char *)0x801000;//16进制
p2 = (unsigned long *)0x810000;
求p1+5=?p2+5=?
p1+5=p1+5*sizeof(unsigned char)=p1+5*1=0x801000+ox5=0x801005
p2+5=p2+5*sizeof(unsigned long)=p1+5*4=0x810000+20=0x810000+0x14=0x810014
而且原来是几进制结果也是几进制,所以最后要转换成16进制。
2、考点:大小端存储
大端模式(大端存储):高位字节存储在低地址中,低位字节存放在高地址中。
小端模式(小端存储):低位字节存放在低地址中,高位字节存储在高地址中。
3、考点:共用体union
char是一个字节=8位二进制=2位16进制
错题:
在小端序的机器中,如果
union X{
int x;
char y[4];
};X a;
a.x = 0x11223344;//16进制
则:y[0]=?y[1]=?y[2]=?y[3]=?
小端存储,低位存在低地址。0x44是最低位,所以它存放在最低的地址。y[0]取的是低地址的值,所以y[0]=0x44,y[3]=0x11
4、当使用free释放掉一个指针内容后,指针变量的值被置为NULL(错×)
free指的是释放该指针所指向的内存资源,指针值没有变化,为了防止指针成为野指针,需要在free后将指针置为NULL。free之后的指针仍然指向原来的堆地址,即仍然可以继续使用(野指针),但很危险。于是你下次不小心使用到该指针(野指针)时,如果操作系统及时制止了这种行为,就会报错(非法操作);如果没报错就会留下很大的隐患。所以最好free了以后再置空,即令指针 = NULL
5、32位系统下任何类型指针的长度都是4个字节
就32位操作系统而言, int* p 和 char* p,指针p的大小都是4字节,至于指针前面的类型主要是针对于指针所指向的变量的。这个类型是告诉cpu取值的时候取多大,指定一个明确的范围。
6、标识符
标识符只能由字母,数字或下划线组成,且第一个字符必须是字母或下划线。
7、&放在=的前面表明这是一个引用,是=后面对象的一个别名。
&放在=的后面表明对该对象进行取地址。是地址运算符。
如int a=10; int &b=a;在这里,意思就是给a变量起了一个新名字b
8、字符串算空间时包含'\0', 但是计算长度时不包含'\0' (strlen时不算,sizeof算),此外‘\n’之类的字符在字符串中也只算一个字符。
9、cout 表示输出语句,endl表示换行(即endline),二者中间的是输出内容
cout << i << endl;
10、do-while的循环要经过了while才开始算。
11、逗号表达式取最右值为结果
12、delete运算符号:
delete 用于释放 new 创建的内存,delete [] 用于释放 new 创建的数组内存。delete 后面只能跟上 new 返回的指针变量。
使用 delete 释放对象内存时会调用对象的析构函数。
不能对一个指针使用多次 delete。因为 delete 以后,此内存已经被收回,可能被分配用于其它数据,因此再次 delete 导致其它数据被非法修改
13、考点:嵌套调用
如下函数在执行f(10)的时候调用了多少次?
int f(int x) {
if(x <= 2) return 1;
return f(x - 2) + f(x - 4) + 1;
}
14、考点:结构体定义的三种方式
①先构造,后定义
struct student{ int num; char name[20]; }; struct student s;
②构造同时定义
struct student{ int num; char name[20]; } s;
③构造同时定义,省略类型名
struct { int num; char name[20]; } s;
但不能定义新变量
struct student{ int num; char name[20]; }; student s; //不能直接用来声明其他变量
typedefine student s; //正确声明
15、考点:数据溢出
执行如下程序代码
char
chr = 127;
int
sum = 200;
chr += 1;
sum += chr;
后,sum的值是()
但是对于c/c++语言来说, char是一个字节, 会发生溢出, 即127加一发生溢出, 0111 1111 --> 1000 0000, 1000 0000为补码-128, 所以结果为200-128=72
还有个例子:
void
test1(){
unsigned
char
array[MAX_CHAR+1],i;
for
(i = 0;i <= MAX_CHAR;i++){
array[i] = i;
}
}
这里 i 是char型,一般char的取值范围是-128到127,而u char 则是0~255,所以 i 的取值范围是0~255。所以当CHAR_MAX常量大于255时,执行i++后,i不能表示256以上的数字,所以导致无限循环。
16、考点:内存对齐、内存分配
union共用体里面以最大成员计算空间。
内存对齐:是内存必须是最大字节类型的整数倍,对齐单位与最大基本类型大小有关。
对齐的原则是:理论上所有成员在分配内存时都是紧接在前一个变量后面依次填充的,但是如果是“以 N 对齐”为原则,那么,如果一行中剩下的空间不足以填充某成员变量,即剩下的空间小于某成员变量的数据类型所占的字节数,则该成员变量在分配内存时另起一行分配。
错题:
union
uti {
int
n;
double
g;
char
ch[9];
} struct
srt {
float
xy;
union
uti uv;
} aa;
考虑内存对齐,则变量aa所占内存的字节数是( )
首先int,float是4字节,double是8字节,char是1字节。 union里面以最大成员计算空间,应该是char[9],占9字节。然后考虑内存对齐,union中最大字节对齐类型为double 8字节,所以struct中应以double为标准对齐,即以8字节为单位对齐。而分配给union的空间应该>=9字节,所以uti实际占16字节。综上,结构体中最大字节对齐类型也是double,所以float需要一个8字节存储(本来float是4个字节),union需要两个8字节存储,共需3*8=24字节。
下面再来举一个例子:
struct STUDENT { char a; char b; char c; char d; char e; int f; }data;
首先最长的数据类型占 4 字节,所以是以 4 对齐。然后 a b c d 都各占 1 字节,此时满 4 字节了,e 再来就要另起一行。f 想紧接着 e 后面分配,但 e 后面还剩 3 字节,小于 int 类型的 4 字节,所以 f 另起一行。即该结构体变量分配内存时如下:
所以该结构体总共占用了12个字节的内存。
17、考点:数组
①考点:数组的第一维大小
二维数组格式:类型 数组名[第一维长度][第二维长度];
②考点:数组名的使用
数组名为指针常量,其值不可更改,因此是不能用字符串对其赋值的。
同理,若str是数组名,则不能执行str++;的语句。 因为这语句实际就是str=str+1,而str是数组名,数组名是常量,所以不能给常量赋值。(可以执行str+1,但是不能str=)
③考点:二维数组定义时不能使用变量定义维数。
举例:
int N=5,b[N][N] = {1, 2, 3, 4, 5};
二维数组定义时,可以省略第一维的定义,但不能省略第二维的定义。
④考点:字符数组
字符串长度不包含'\0',所以字符数组输入的字符长度要小于字符数组的定义长度。
⑤考点:维数的表达式类型
在 C 语言中,C99除外,一维数组的定义方式为: 元素类型 数组名[E]; 其中E是整型常量表达式
⑥考点:指针数组与数组指针,指针函数与函数指针
int *p[5] 表示指针数组,指一个数组里面装着指针(5个指针元素)
int (*p)[5]表示数组指针,表示一个指向数组的指针(指向长度为5类型为int型的数组)
int *(ptr[4]):也是数组指针,ptr是数组,存放了4个指向int类型的指针
int *p(void) 表示函数,此函数无参,返回整型指针。
int (*p)(void) 表示函数指针,可以指向无参,且返回值为整型指针的函数(指向int型函数的指针)
⑦考点:数组与间接访问、取址
int a[
5
] = {
1
,
3
,
5
,
7
,
9
};
int *p = (int *)(&a+
1
);
printf(
"%d,%d"
,*(a+
1
),*(p
-1
));
&a+1不是首地址+1,系统会认为加了一个整个a数组,偏移了整个数组a的大小。&a是数组指针,其类型为int(*)[5]; 而指针加1要根据指针类型加上一定的值,a是长度为5的int数组指针,所以要加5*sizeof(int),所以p实际是a[5],指向数组的下一个位置
*(a+1)其实很简单就是指a[1],输出为3.
但是p与(&a+1)类型是不一样的,这点非常重要,所以p-1只会减去sizeof(int*),而p是指向数组的下一个位置,所以p-1就指向数组的最后一个元素.
int a[4][3] = {1,2,3,4,5,6,7,8,9,10,11,12};
int (*prt)[3] = a, *p = a[0];
prt是int*[3]类型的数组指针,(*(prt+1))[2]可表示a[1][2],取其[2]相当于将当前地址作为首地址再往后移2行;同样也可以用* ( * (a+1)+2)来表示。
void
fun(
const
char
** m) {
m++;
cout << *m << endl; //输出、换行
}
char* a[] = {
"MORNING"
,
"AFTERNOON"
,
"EVENING"
};
const
char
** n;
n = a;
fun(n);
这里m指针是指针的指针,指向的是char*类型,代换进去就是m=a,是第一个字符串的地址,指向的字符串长度是7字节。那么m地址实际所加上的值是7,也就是跳过了“MORNING”。m++后指向“AFTERNOON”的首地址,解引用后,m就是字符串“AFTERNOON”
18、在函数内部定义的非指针变量不能作为返回值
如题,如果定义的p不是指针:
char* getmemory(void){
char p[]= " hello world";
return p;
}
p是数组名,返回p就是返回数组p,因为函数调用结束后该数组会被释放,所以返回会得到随机地址(出错)。
如果p改为指针:
char* getmemory(void)
{
char* p=”hello world”;
return p;
}
则p会指向存放字符串常量的地址,调用函数结束字符串常量不会消失,所以返回常量的地址不会出错。
19、考点:树
求树的高度
struct Celode
{
struct Celode *lchild; //左分支指针
int element;
struct Celode *rChild; //右分支指针
}
int DoSomething(struct Celode *ptr)
{
int value = 0;
if (ptr != NULL)
{
if (ptr -> lChild != NULL)
value = 1 + DoSomething(ptr -> lChild);
if (ptr -> rChild != NULL)
value = max(value, 1 + DoSomething(ptr -> rChild)); //左子树右子树的高度取一个max,所以就是树的高度
}
return (value);
}
20、考点:控制表达式的类型
switch语句后的控制表达式只能是short、char、int、long整数类型和枚举类型,不能是float,double和boolean类型
20、考点:循环条件
for(j = 0, k = -1; k = 1; j++, k++)
printf("****\n");问循环了几次?
此循环的循环条件为k=1,是赋值语句所以永远为真,所以是无限循环。
21、考点:0和‘0’的区别
循环控制表达式中0和 ‘0’ 是不一样的,后者是个数,相当于真,前者相当于假。
‘1’表示字符1,对应ASCII码为49,所以式子int a=‘1’的值为49
22、考点:宏定义代换
错题:
#define N 2
#define M N + 1
#define NUM (M + 1) * M / 2
main(){
printf("%d\n", NUM);
}
宏定义只是简单的文本替换,(2+1+1)*2+1/2=8
还有一个例子:
#define INT_PTR int*
typedef
int
* int_ptr;
INT_PTR
a, b;
int_ptr c, d;
后两句分别是int* a, b;(a是指针类型,b是int类型)
和 int* c;
int
* d;(c,d都是指针类型)
23、考点:printf输出格式
printf
(
"%-6.2e\n", x); //
输出的宽度为6个字符宽,小数位占2位(四舍五入),不足时后面添0;“e”表示用指数形式输出;“-”表示采用左对齐方式(默认为右对齐)。
printf
(
"%6.9s\n", x);//
表示输出一个长度不小于6且不大于9的字符串。若大于9, 则第9个字符以后的内容将被删除。
(2)C 语言中用 "%%" 打印输出字符 "%", 所以 %%d, 输出为 %d 两个普通字符 , 而不是格式控制符 "%d" 的含义
24、return后面括号中表达式的值即是函数的值,这句话是错误的,当return后面表达式值的类型与函数的类型不一致时,需要强制类型转化。
25、考点:设备输入与输出
用户双击鼠标时产生的消息序列,下面正确的是()
WM_LBUTTONDOWN,WM_LBUTTONUP,WM_LBUTTONDBLCLK,WM_LBUTTONUP
双击即点击左键两下,第一次触发LBUTTONDOWN和LBUTTONUP,第二次点击时触发双击事件LBUTTONDBLCLK(doubleclick),放掉再触发LBUTTONUP
26、考点:运算符的优先级
(1)基本的优先等级需要牢记:指针最优,单目运算高于双目运算,先乘除(取模),后加减,先算数运算,后移位,最后位运算,逻辑运算最最后。相同优先级按结合顺序计算,大多数从左向右,只有单目运算符、条件运算符、赋值运算符是自右向左结合。
设整型变量n的值为2,执行语句“n+=n-=n*n”后,n的值是( )
n += ( n -= n*n ),先求括号内的值为2-4=-2,于是n=-2,然后n += n 求得n 等于-2+(-2)=-4
(2)逻辑与 &&、逻辑或 || 均有“短路”特性:
对于与运算而言,如果左边表达式值为0(逻辑假),那么整个逻辑运算结果就是0(逻辑假),不会对右侧表达式进行运算了。(与就是想乘)
对于或运算而言,如果左边表达式值为非0(逻辑真),那么整个逻辑运算结果就是非0(逻辑真),不会对右侧表达式进行运算了。(或就是相加)
int x=12, y=15, z;
z = ( x || ( y -= x ) );
首先,执行的是 x||(y-=x) 中||左侧部分,x为12,故非0值或任意值均为1,||左侧非零,||右侧就不执行了。故z=1,而y不变,仍然是15。
27、求余%
是唯一要求运算必须是整型的运算符。取余操作对浮点数和double双精度数无意义
27、求除 /
当多个精度的数字同时进行运算时,最终结果以最高精度为准。在多数情况下,整数和小数的各级混合运算中,一般结果都是double类型的。为方便可以这样处理:double m = x/y,当然m是double类型的所以也不会报错,而如果你写成int m = x/y,编译器报错提示的时候就会让你转换成float或者进行强制转换成int,他是不会提示你转换成double的(因为向上兼容)
28、考点:字符串函数
①考点:字符串比较
C 库函数 int strcmp(const char *str1, const char *str2) 把 str1 所指向的字符串和 str2 所指向的字符串进行比较。
- 如果返回值 < 0,则表示 str1 小于 str2
- 如果返回值 > 0,则表示 str2 小于 str1
- 如果返回值 = 0,则表示 str1 等于 str2
②考点:字符串长度
strlen(s)计算字符串的长度时不会将结束符‘\0’算入,即字符串长度。
区分于sizeof(数据在内存中所占用的存储空间。)
当用strcat拼接两个字符串时,结果字符串占用的内存空间是两个原串占用空间之和减一
③字符串写入gets(ss);
如果写入的数组本身有内容,则写入后会被完全覆盖。
29、考点:不同类型数据的存储方式
负数在内存中存储的是补码形式
正数在内存中以原码形式存储
浮点数是采用某种规则转换后存储
char型是直接将其对应的ASCII码存储(此答案有争议,char也可以视为补码)
30、补码运算:
(1)不同类型的数据赋值时它们的补码相等。
例:
short si = -32767;
unsigned short usi = si;
先把-32767表示成原码形式是(因为补码不是一步可以得到的,先原码再补码)
(-32767)原码=1111 1111 1111 1111
(-32767)补码 =1000 0000 0000 0001
再把这个补码赋给usi,usi会把最高位符号位1也当做数值位
usi=1000 0000 0000 0001=32769
(2)正数的补码等于本身,负数的补码等于符号位以外求反+1。
30、实参可以是常量、变量或表达式,但是形参只能是变量。
31、位运算
(1)c1^c2 是按位异或 ,~c2是按位取反
(2)浮点数无法进行位运算。程序中的所有数在计算机内存中都是以二进制的形式储存的。位运算就是直接对整数在内存中的二进制位进行操作,而浮点数是无法精确的转化为二进制表示的,所以是无法进行位运算的。
32、自加自减
printf
(
"%c,"
,y++);//先输出y的字符格式,再对y进行自加
33、考点:类class
class a {
public:
static int i;
};
int main()
{
a a1;
a1.i = 3;//对象修改静态变量
a::i = 4;//类直接修改静态变量
}
静态成员与类相关联,而不是与对象相关联。默认实参在编译时就已经确定,因此即使没有对象实例也可以使用静态成员作为默认实参。
下列关于类中的静态成员的说法错误的是(D)
A、虽然静态成员不属于类的某个对象,但是我们仍然可以使用类的对象、引用或者指针来访问静态成员
B、成员函数不用通过作用域运算符就能直接使用静态成员
C、静态数据成员不是由类的构造函数初始化的
D、静态成员不可以作为默认实参
类的所有成员共享一个静态成员。
静态类数据成员必须在类的内部声明,在类的外部初始化。
在访问静态成员时,可以通过对象访问,也可以通过类访问。
通过this指针访问的数据成员和方法成员都必须是类的非静态成员。
34、
假定AB为一个类,则执行 “AB ab = new AB(a,5);”语句时将自动调用该类的( A )。
A、带参构造函数
B、无参构造函数
C、拷贝构造函数
D、重载赋值运算
记住就好了,这个是实例化对象 :
new AB(); //表示使用无参构造函数实例化对象调用的无参构造函数
new AB(a,5); //表示调用的是有参构造函数 new AB (Object i , int j );
ab是类AB实例,new一个类的时候就是调用构造方法,而题目中构造方法带参数,可知调用的是带参的构造方法。
35、考点:结构体
①考点:char buffer[ 0 ];
C代码中可能会出现如下类型的结构体定义:
typedef struct holder {
struct holder *next;
struct holder *prev;
char buffer[ 0 ];
} holder;最后一行 char data[ 0 ] 作用是(ABC)
A、方便管理内存缓冲区
B、减少内存碎片化
C、使结构体数据对齐
D、没有作用
1. 方便管理内存缓冲区:如果用指针 char* 代替 char data[0] 来指向新开辟的空间,需要两次malloc也需要两次free。用char data[0],一次malloc即完成,方便管理缓冲区。
2. 减少内存碎片化:如果在struct尾部用指针*指向新开辟的buffer长度,struct本身相较buffer长度是很小的,即碎片化的内存。而用char data[0]指向新开辟的buffer,struct和buffer的空间是连续的。即减少了内存的碎片化。
3. 节省空间,相较用指针指向新开辟的str,data[0]是不占用内存的,而指针占用4字节。
PS:使用指针和data[0]有以下区别:
1.地址的连续性,data[0]和结构体是一个连续的存储空间,使用指针就不是连续的。连续的存储空间通过不同的强转使用起来比较灵活。
2.data[0]不占用任何内存,*data占用4字节 。
3.建议:C++的类中可以使用 *data但是不要使用data[0],因为这样使用可能会导致类中的一些看不到的东西被覆盖。
4、在给定的代码中,char buffer[0]是一个灵活数组成员(flexible array member)。这是一种常见的C语言技巧,用于在结构体中创建一个可变长度的数组。在这个结构体中,buffer被定义为一个长度为0的char数组。尽管长度为0,但它在结构体中的作用是为了占位,为后续的动态内存分配提供空间。通常,在使用这种灵活数组成员的结构体时,程序员会在运行时动态分配内存,使得buffer可以根据实际需求分配所需的空间。这样,结构体可以根据需要存储不同长度的数据。
例如,可以通过以下方式为结构体分配内存并设置合适的长度:
1 2 |
|
通过灵活数组成员,可以根据需要动态分配更多的内存,然后将数据存储在buffer中。这样,buffer的长度可以根据实际情况进行调整。 - By ChatGPT
36、求x的二进制数中有多少个1
int func(int x) {
int countx = 0;
while(x) {
countx ++;
x = x & (x - 1);
}
return countx;
}
每次循环,把从右向左数的第一个1,后面的所有的数字都变为0。如x=1000110,x&(x-1)=1000100就是把x右边的第一个1后面的数变为0(包括1)。如果10000的话,结果就是00000了!这样就可以利用这个特性来计算这个十进制书转化为二进制数有多少个1!
如果改为x = x | (x - 1);则变为求x的二进制数中有多少个0
37、考点:EOF
表示文件结束符。
在 while 循环中以 EOF 作为文件结束标志。
这种以 EOF 作为文件结束标志的文件,必须是文本文件(二进制文件则不是)。
EOF的值为-1 ,在文本文件中,数据都是以字符的 ASCII 代码值的形式存放,而 ASCII 代码值的范围是 0~255 ,不可能出现 -1 ,因此可以用 EOF 作为文件结束标志。
对于文本文件来说,当fgetc函数读到文件尾后未读取到字符才会返回EOF标志(-1)。
38、考点:实参和形参的值传递
在值传递过程中,实参和形参位于内存中两个不同地址中,实参先自己复制一次拷贝,再把拷贝复制给形参。所以,在值传递过程中,形参的变化不会对实参有任何的影响。
形参变量只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只在函数内部有效。
#include <stdio.h>
#include <stdlib.h>
void fun(int *p1, int *p2, int *s) {
s = (int *)malloc(sizeof(int));
*s = *p1 + *(p2++);
}
int main() {
int a[2] = {1, 2}, b[2] = {10, 20}, *s = a;
fun(a, b, s);
printf("%d \n", *s);
}
求:最后输出的值
形参s只是实参s的拷贝(将实参s的地址拷贝给形参s),接着在fun()中用malloc开辟了内空间,修改了形参s的指向,因此此时形参s已经不指向原来的物理地址了,即形参s已经不指向a了,所以后面的操作不会改变实参s所指向的值,即实参s仍然指向a[0]。
39、考点:返回值类型
一个函数没有返回值时,是void型,此时的void关键字不能省略;
一个函数省略返回值类型时,默认是 int型;
40、考点:#include<file.h> 与 #include "file.h"的区别?
#include <>表示直接从库中查找,而#include “ ”表示在当前目录的相对路径中找,找不到再在库中查找。一般自己写的头文件用#include"",而使用库函数用#include<>
41、
关于c语言,下列说法正确的是()
A、结构只能包含一种数据类型(×)
B、可以比较两个联合是否相等(×)
C、结构的标记名是可以没有的(√)
D、不同结构的成员必须有唯一的名字(×)
E、关键字typedef用来定义新的数据类型(×)
F、结构总是以传引用的方式传递给函数(×)正确:传值的方式
G、结构是不可以比较的(√)
42、考点:数据类型转换,符号拓展
unsigned short A = 10;
printf("~A = %u\n", ~A);
char c = 128;
printf("c=%d\n", c);
(1)%u表示按unsigned int型格式输出。按%u输出,最高位的1表示数值,不表示符号。
(2)按%d输出,最高位的1表示符号。有符号数使用补码表示,即原码按位取反加1(反码的值等于最大值f=15减去原码的值)。若按%d形式输出,由于是补码形式存储的,所以0xfffffff5的原码为0x8000000b(原码=补码求补码,即补码求反加一,或减一求反,最高位的1不变)
(3)char的大小是一个字节也就是8位,所以无符号的char的取值范围为0~255,即0000 0000 ~ 1111 1111。而通常情况下也就是有符号的char的范围是原来的一半,也就是-128到127,即1000 0000 ~ 0111 1111。
同理short的大小是两个字节16位,所以无符号的short的取值范围为0x0000 ~ 0xffff。
(4)short和char的无符号和有符号形式都会先转换为int型,int型是32位。
(5)符号扩展:当用更多的内存存储某一个有符号数时,由于符号位位于该数的第一位,扩展之后,符号位仍然需要位于第一位,所以,当拓展一个正数时将拓展的高位全赋为0,符号位仍是0;而当扩展一个负数的时候需要将扩展的高位全赋为1。比如一个用一个8位二进制表示-1,则是[10000001] ,如果把这个数用16位二进制表示时,则为[11111111 10000001]。
A的16位二进制表示为: 0000 0000 0000 1010 十六进制↓
A的32位二进制表示为:0000 0000 0000 0000 0000 0000 0000 1010 0x0000000a
~A的32位二进制表示为: 1111 1111 1111 1111 1111 1111 1111 0101 0xfffffff5
因为按%u输出,所以最高位的1表示数值,不表示符号。由于32位全1的值等于(2^32-1),所以~A=(2^32-1)-10=4294967285,或15*16^7+15^16^6+15*16^5+15*16^4+15*16^3+15*16^2+15*16+5=4294967285;
通常情况下也就是有符号的char的范围是-128到127,即1000 0000 ~ 0111 1111。所以128已经溢值,而在C语言中是循环的,即最大值加一变为最小值,最小值减一变为最大值,故128溢出后转化为int即为-128。
从符号拓展来看,c之所以是-128,是因为128在机器中以补码形式存在[1000 0000],然后因扩展成int类型,所以为[1111 1111 1111 1111 1111 1111 1000 0000],此时该数是补码,需-1并取反转换成原码[1000 0000 0000 0000 0000 0000 1000 0000],即-128。
43、考点:宏指令
#define 定义一个预处理宏(#define多次定义不会报错)
#undef 取消宏的定义
#if 编译预处理中的条件命令,相当于C语法中的if语句
#ifdef 判断某个宏是否被定义,若已定义,执行随后的语句
#ifndef 与#ifdef相反,判断某个宏是否未被定义
#elif 若#if, #ifdef, #ifndef或前面的#elif条件不满足,则执行#elif之后的语句,相当于C语
法中的else-if(扩展条件)
#else 与#if, #ifdef, #ifndef对应, 若这些条件不满足,则执行#else之后的语句,相当于C语
法中的else(扩展条件)
#endif #if, #ifdef, #ifndef这些条件命令的结束标志。#if和#endif是配对的,叫做条件编译
指令,如果满足#if后面的条件,就编译#if和 #endif之间的程序段,否则不编译。
defined 与#if, #elif配合使用,判断某个宏是否被定义
注:
(1)宏替换不会占用程序运行时间。
44、赋值语句的值等于所赋的值,逗号表达式的值等于左后一个表达式的值。
45、考点:语法错误
对于下面代码段说法正确的是()
int
main() {
int
a,b;
scanf
(
"%d,%d"
,&a,&b);
if
(a>b) a=b;b=a;
else
a++;b++;
printf
(
"%d,%d"
,a,b);
}
A、有语法错误不能通过编译 B、若输入4,5则输出5,6 C、若输入5,4则输出4,5 D、若输入5,4则输出5,5
【解释】在if和else之间如果有多条语句,则必须使用复合语句,否则程序语法错
误。该程序if和else之间有两条语句a=b;b=a;,但没有加{ },是错误的。故正确答
案为A。
46、位与:^ ,位左移:<<,位右移:>>
47、 考点:枚举
(1)关键字:enum
(2)枚举数据表的值都是整数。第一个枚举成员的默认值为整型的0,后续枚举成员的值默认在前一个成员上加1。也可以人为设定枚举成员的值,从而自定义某个范围内的整数。
(3)枚举类型可以进行比较。
(4)typedef enum则是用来定义一个数据类型,那么该类型的变量值只能在enum定义的范围内取
enum weekday {Mon=1,Tue,Wed,Thu,Fri,Sat,Sun};
enum weekday workday;
typedef enum {Jan=1,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,dec} Mon;
Mon a, b;
(5)不同的枚举类型中也不能存在同名的命名常量。
(6)枚举类型变量的值只能在枚举成员中取。
48、考点:关键字const
int * const x = &y;
const int *x = &y;
若const限定符在*之前,则const限定的是*ptr而不限定ptr。也就是说,ptr可以改变其所指向的对象,但不能通过该指针修改其所指向对象的值。
若const限定符在*之后,则const限定的是ptr而不限定*ptr。也就是说,ptr不可以改变其所指向的对象,但能通过该指针修改其所指向对象的值。
若在*之前有const限定符且在*之后也有const限定符,则ptr与*ptr都被限定。也就是说,ptr既不可以改变其所指向的对象,也不能通过该指针修改其所指向对象的值。
另外:只要 在*之后有 const限定符,则该指针在声明时必须初始化。
49、考点:预处理、预编译
(1)C语言由源代码生成的各阶段如下,C源程序->编译预处理->编译->优化程序->汇编程序->链接程序->可执行文件
(2)预处理过程读入源代码之后,会检查代码里包含的预处理指令,完成诸如包含其他源文件、定义宏的处理。C选项中,诸如__DATA__、__FILE__、__LINE__、__STDC_VERSION__、__TIME__等,属于预定义宏,因此在预编译处理阶段。
(3)预处理指令可以在主程序任何位置。
(4)在源文件的一行上只能有一条预处理命令。
(5)
50、考点:指令的运行周期
错题:使用C语言将一个1G字节的字符数组从头到尾全部设置为字’A’,在一台典型的当代PC上,需要花费的CPU时间的数量级最接近()
执行1条语句约1ns即10的-9次方秒,1G=1024M=1024*1024k=1024*1024*1024byte,每次赋值1byte都要执行一次语句,故至少花费1024*1024*1024*10^-9=1.073741824s约等于1s
51、考点:关键字static
有局部静态变量和全局静态变量,静态变量存储于静态数据区,只需要初始化与一次,所以局部静态变量不会消失。