以下叙述中不正确的是(B) D
A)在不同的函数中可以使用相同名字的变量
B)函数中的形式参数是在栈中保存
C)在一个函数内定义的变量只在本函数范围内有效
D)在一个函数内复合语句中定义的变量在本函数范围内有效
本题错选了B是因为对形式参数的定义不明确,只想到了形式参数不是实际存在的,
而忽略了形式参数的存在就是为了接受实参传来的值,进而保存在栈中。
而D就错的比较明显了,复合语句即大括号中的语句,
显然其作用域只在大括号所在范围内。
void example() 1
2
3
4
5
6
7
8
9
10{
int i;
char acNew[20];
for(i = 0; i < 5; i++)
{
acNew[i] = '0';
}
printf("%d\\n" ,strlen(acNew));
return ;
}以上代码的输出结果为(A)D
A)0 B)5 C)6 D)不确定这一题是错在了错把字符’0’当成了’/0’。
由于strlen()函数是通过判断’/0’来判断字符串是否结束,
数组acNew[20]并没有初始化,只给前5个元素赋了字符’0’,其十进制值为48。
因此strlen()函数返回的值是一个大于等于5的不确定的值,因为函数不知道在哪里会遇到’/0’。
全局变量可以定义在被多个.c文件包含着的头文件中(A)B
A)正确 B)错误
编译器在编译程序时,会有两个动作,一是编译每一个文件生成类似于*.obj的文件,然后链接这些文件。
因此,在头文件中的全局变量将会被多次定义,进而产生错误。
所以我们要避免在头文件中定义全局变量。
设有以下宏定义:
1
2
3则执行语句:z = 2 * (N + Y(5+1));后,z的值为()
A)出错 B)60 C)48 D)70
宏定义的问题,大多都是括号的问题,这个做错是粗心了。
z = 2 * (4 + ((4+2)* 5 + 1)
因此在使用宏的时候一定要注意括号。
有如下宏定义和结构定义
1
2
3
4
5
6
7
8
9
struct _Record_Struct
{
unsigned char Env_Alarm_ID : 4;
unsigned char Para1 : 2;
unsigned char state;
unsigned avail : 1;
}*Env_Alarm_Record;
struct _Record_Struct *pointer = (struct _Record_Struct*)malloc(sizeof(struct _Record_Struct) * MAX_SIZE);当A=2, B=3时,pointer分配(C)个字节的空间。 D
A)20 B)15 C)11 D)9这一题是因为对位段的不熟悉以及粗心弄错宏定义的括号从而选错答案,
该结构体在内存中的存储方式如下图所示,由图可知该结构体在内存中占3个字节的内存空间, 因此sizeof(struct _Record_Struct)为3, 从而 3 * A + B ,即9。
在X86,VC++6.0环境下,有下列程序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int main()
{
char c;
unsigned char uc;
unsigned short us;
c = 128;
uc = 128;
us = c + uc;
printf("0x%x ", us);
us = (unsigned char)c + uc;
printf("0x%x ", us);
us = c + (char)uc;
printf("0x%x ", us);
return 0;
}输出结果为(C)A
A)0x0 0x100 0xff00
B) 0x100 0x100 0xff00
C) 0x100 0x100 0x0
D) 0x0 0x100 0x0本题是因为对类型转换不熟悉,分析过程如下:
char的范围是 -128 ~ 127
unsigned char范围是 0 ~ 255
unsigned short范围是 0 ~ 65535
c = 128;
128编译器会把128当作一个整形变量,占用4个字节,即32位
0000 0000 0000 0000 0000 0000 1000 0000
在char类型中,1000 0000即表示-128。
uc = 128;
没什么说的,取128二进制的后8位得128;
然后就是us:us = c + uc;
运算时将转为32位,c为负数,进而前面补符号位1,无符号数uc前面补0。
c: 1111 1111 1111 1111 1111 1111 1000 0000
uc:0000 0000 0000 0000 0000 0000 1000 0000
相加得0000 0000 0000 0000 0000 0000 0000 0000
因为us占2个字节,因此前面补0,即此时的us为0x0
us = (unsigned char)c + uc;
当c被强制类型转换为无符号后,前面补0,从而有下面结果:
c: 0000 0000 0000 0000 0000 0000 1000 0000
uc:0000 0000 0000 0000 0000 0000 1000 0000
相加得:0000 0000 0000 0000 0000 0001 0000 0000
因此us为0000 0001 0000 0000,即十六进制0x100
us = c + (char)uc;
c: 1111 1111 1111 1111 1111 1111 1000 0000
uc:1111 1111 1111 1111 1111 1111 1000 0000
相加1111 1111 1111 1111 1111 1111 0000 0000
即us为0xff00
unsigned short *pucCharArray[10][10]; 1
2
3
4
5
6
7
8
9
10
11
12typedef union unRec
{
unsigned long ullndex;
unsigned short usLevel[7];
unsigned char ucPos;
}REC_S;
REC_S stMax, *pstMax;
四字节对齐方式时:
sizeof(pucCharArray) = 40 400
sizeof(stMax) = 20 16
sizeof(pstMax) = 4
sizeof(*pstMax) = 20 16本题考察指针数组在内存中的存储,以及联合在内存中存在的内存对齐。
pucCharArray为指针类型,每一个元素占用4个字节的空间,
并且这是一个二维数组,且sizeof()内只包含数组名,
因此是求整个数组占用的空间大小,即41010 =400.
stMax是个联合,因此其占用空间大小为其中最大变量所占用的空间大小,
即 usLevel[7]占用14个字节,又因为四字节对齐,所以其占用大小为16个字节。
pstMax为一个指针变量,占用4个字节。
*pstMax虽然没有指向某个REC_S,然而其指向的空间大小还是可以求的,即一个RESC_S所占的空间大小。
struct tagAAA 1
2
3
4
5
6
7
8
9{
unsigned char ucld : 1;
unsigned char ucPara0 : 2;
unsigned char ucState : 6;
unsigned char ucTail : 4;
unsigned char ucAvail;
unsigned char ucTail2 : 4;
unsigned char ucData;
}AAA_S;问:AAA_S在分别为1字节对齐(char)和四字节对齐(int)的情况下,占用的空间大小是:19,20 6,6
本题主要考察结构体的内存对齐现象,以及位段的掌握。
内存对齐是典型的以空间换时间的方法,
若不内存不对齐,找这个变量有时就需要两次访问,而如果内存对齐,则可以一次就访问到。
内存中储存的顺序如下图:从左至右,从上至下,每种不同颜色依次代表结构体中不同的变量。 可以得知该结构体所占空间大小为6个字节。
ENUM_A 1
2
3
4
5
6
7
8
9{
X1,
Y1,
Z1 = 255,
A1,
B1
};
enum ENUM_A enumA = Y1;
enum ENUM_A enumB = B1;则enumA = ,enumB =
本题考察枚举。
枚举的第一个变量一定是从0开始,因此:
X1 = 0
Y1 = 1
由于Z1赋值为255,
因此
A1 = 256
B1 = 257
- 以下程序的执行结果为
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
int main()
{
unsigned char puc[4];
struct tagPIM
{
unsigned char ucPiml;
unsigned char ucData0 : 1;
unsigned char ucData1 : 2;
unsigned char ucData2 : 3;
}*pstPimData;
pstPimData = (struct tagPIM*)puc;
memset(puc,0,4);
pstPimData->ucPiml = 2;
pstPimData->ucData0 = 3;
pstPimData->ucData1 = 4;
pstPimData->ucData2 = 5;
printf("%02x %02x %02x %02x\\n", puc[0],puc[1],puc[2],puc[3]);
return 0;
}
本题主要考察位段,puc[4]长度为4个字节,
结构体tagPIM中ucPiml占用1个字节的内存空间,
ucData0,ucData1,ucData2分别占用1位,2位,3位,
由于结构体内存对齐,因此这三个变量总共占用1个字节
2 0000 0000 0000 0000 0000 0000 0000 0010
当给pstPimData->ucPiml赋值时,取(int)2 的1字节0000 0010,即2
所以puc[0]为02,
3 0000 0000 0000 0000 0000 0000 0000 0011
当给pstPimData->ucData0赋值时,取(int)3的1位得1,
4 0000 0000 0000 0000 0000 0000 0000 0100
给pstPimData->ucData1赋值时,取(int)4的2位得00,
5 0000 0000 0000 0000 0000 0000 0000 0101
给pstPimData->ucData2赋值时,取(int)5的3位得101,
由于标准没有规定位段在在一个字节中是从左向右存储或是从右向左存储,
我所使用的平台中位段的使用中是由高地址向低地址依次占用的,前两位因为内存对齐浪费掉,
因此,第二个字节中存储的数据为 0010 1001,即0x29
puc中的后两个字节没有发生变化,因此其值依旧为0,
答案即 0x02 0x29 0x00 0x00
下面的代码中,函数Test执行完毕后,希望输出1,指出错误:
void VarInit(unsigned char *pucArg) 1
2
3
4
5
6
7
8
9
10
11{
*pucArg = 1;
return;
}
void Test()
{
unsigned long ulGlobal;
VarInit((unsigned char*)&ulGlobal);
printf("%lu", ulGlobal);
return;
}本题错在了没有对ulGlobal进行初始化,而函数VarInit只对一个字节赋值为1,
而unsigned long 类型的ulGlobal变量有四个字节,因此其值不确定
此外函数VarInit((unsigned char*)&ulGlobal);传参没有任何问题。
找出下面题目中的错误:
#define ID_LEN 32 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23struct STR_A
{
char aucID[ID_LEN];
int iA;
};
struct STR_B
{
char *paucID;
int iB;
};
void funcA(struct STR_A stA, struct STR_B *pstB)
{
pstB->paucID = stA.aucID;
}
void main()
{
STR_A stA = { 0 };
STR_B stB;
strcpy(stA.aucID, "12345");
funcA(stA, &stB);
printf("%s\\n", stB.paucID);
}本题错在了函数funcA把pstB->paucID指向了函数中的非指针参数,
因此当函数生命周期结束后,这份形参将从函数栈中被释放,
从而在main函数中stB得不到正确的结果。
typedef unsigned char _UC; 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15typedef unsigned long _UL;
void ConvertCode(_UC *p_byte, _UC num)
{
_UL i;
for (i = 0; i < num; i++)
{
p_byte[i] = ((p_byte[i] & 0xF0) >> 4) | ((p_byte[i] & 0x0F) << 4);
}
}
void main()
{
_UC *str = NULL;
ConvertCode(str,MAX_LEN);
}本题主要错在了对空指针的解引用操作上,
代码本意是想完成对unsigned char类型数据的前后四位的反转
#define MAX_PRAM_LENGTH 10000 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15typedef struct
{
unsigned char ucCommand;
unsigned short usLength;
unsigned char Para[MAX_PRAM_LENGTH];
}DEBUG_MSG;
void PrintDebufMsg(DEBUG_MSG DebugMessage)
{
int i;
printf("]nCommand = %d", DebugMessage.ucCommand);
for (i = 0; i < DebugMessage.usLength && i < MAX_PRAM_LENGTH; i++)
{
printf("\\nPara[%d] = 0x%x", i, DebugMessage.Para[i]);
}
}本题的性能问题主要是在使用结构体来传参,
结构体中有一个10000字节的数组,
当调用函数时,将会占用函数帧栈上的大量空间,因此不可取。
一般在函数中使用结构体传参时,只传递结构体的地址即可。