3. 有以下程序段
char acArr[]= "ABCDE";
char *pcPtr;
for(pcPtr = acArr; pcPtr < acArr + 5; pcPtr++)
{
printf("%s/n", pcPtr);
}
return;
输出结果是( )
A) ABCD B) A C) E D) ABCDE
B D BCDE
C C CDE
D B DE
E A E
答案:D
补充一个类似的题:
int main()
{
long ulCnt1 = 0,ulCnt2 = 0;
char *ch = "aha!";
while(*ch)
{
switch(*ch)
{
case 'a':
case 'h':
ulCnt2++;
default:
ulCnt1++;
}
ch++;
}
printf("%u,%u\n",ulCnt1,ulCnt2);
return 0;
}
结果为:4,3
执行过程,*ch的变化,由aha!变为ha!,再变为a!,直到最后一个字符!
若字符串改为:bhb!,则结果为:4,1
17.在函数内部定义的变量(静态变量、寄存器变量等特殊变量除外)的内存是在栈内存中,所以在定义函数内部的变量的时候,一定要保证
栈不能够溢出。如果临时变量占用空间较大,应该使用内存申请的方式(即使用malloc(sizeof(xxx))的方式),这样该变量指向的内存就是在堆内存中了,这样,程序返回时栈销毁而堆内存中的没有销毁。
20. int *(*ptr)();
则以下叙述中正确的是( )
A) ptr是指向一维组数的指针变量
B) ptr是指向int型数据的指针变量
C) ptr是指向函数的指针,该函数返回一个int型数据
D) ptr是指向函数的指针,该函数的返回值是指向int型数据的指针
答案:D
1. .struct tagAAA
{
unsigned char ucId:1;
unsigned char ucPara0:2;
unsigned char ucState:6;
unsigned char ucTail:4;
unsigned char ucAvail;
unsigned char ucTail2:4;
unsigned long ulData;
}AAA_S;
问:AAA_S在字节对齐分别为1、4的情况下,占用的空间大小是多少?
答案:9 12。字节对齐方式为1的情况下,ucId:1和ucPara0:2和用一个字节,ucState:6、unTail:4、ucAvail、ucTail2各占用一个字节,最后
long型占用4个字节,所以共占用9个字节;在4字节对齐时候,前五个变量占用4个字节,第5、6变量又占用4个字节,最后long型仍然是四
个字节,所以共使用12个变量。
2.typedef struct tagTest
{
UCHAR ucFlag;
ULONG ulLen;
}TEST_S;
TEST_S test[10];
四字节对齐方式时: sizeof(TEST_S) = ______, sizeof(test)________.
答案:8 80。第一个运算是针对结构体变量类型,第二个是针对具体的变量
4.#pragma pack(4)/*编译选项,表示4字节对齐*/
int main(int argc, char* argv[])
{
struct tagTest1
{
short a;
char d;
long b;
long c;
};
struct tagTest2
{
long b;
short c;
char d;
long a;
};
struct tagTest3
{
short c;
long b;
char d;
long a;
};
struct tagTest1 stT1;
struct tagTest2 stT2;
struct tagTest3 stT3;
printf("%d %d %d", sizeof(stT1), sizeof(stT2), sizeof(stT3));
return 0;
}
#pragma pack()(编译选项结束)
请问输出结果是:_________
答案:12 12 16
6.以下程序的输出结果是________.
#include <stdio.h>
int fun(int x,int y)
{
static int m = 0;
static int i = 2;
i += m + 1;
m = i + x + y;
return m;
}
void main()
{
int j = 4;
int m = 1;
int k;
k = fun(j, m);
printf("%d,", k);
k=fun(j, m);
printf("%d/n", k);
return;
}
答案:8 17
8.在VRP中,实现了strncpy类似的函数,定义如下:
#define CHAR char
#define ULONG unsigned long
#define VOID void
#define MACRO_COPYWORLDLENGTH 4
CHAR *VOS_strncpy(CHAR *pcDest, const CHAR *szSrc, ULONG ulLength)
{
CHAR *pcPoint = pcDest;
if(( NULL == szSrc ) || ( NULL == pcDest ) )
{
return NULL;
}
while(ulLength && (*pcPoint = *szSrc))/*这里采用了在判断语句中赋值的方式(*pcPoint = *szSrc),建议尽量不使用*/
{
pcPoint++;
szSrc++;
ulLength--;
}
if(!ulLength)
{
*pcPoint = '/0';
}
return pcDest;
}
VOID main(VOID)
{
CHAR szStrBuf[ ] = "1234567890";
CHAR szStrBuf1[ ] = "1234567890";
CHAR *szHelloWorld = "Hello World!";
strncpy(szStrBuf, szHelloWorld, MACRO_COPYWORLDLENGTH);
VOS_strncpy(szStrBuf1, szHelloWorld, MACRO_COPYWORLDLENGTH);
printf("%s %s", szStrBuf, szStrBuf1);
}
程序的输出结果为________
答案:Hell567890 Hell
10. typedef struct Head
{
UCHAR aucSrc[6];
ULONG ulType;
} HEAD_S;
在强制一字节对齐情况下,请指出sizeof(HEAD_S) = ________;
在强制二字节对齐情况下,请指出sizeof(HEAD_S) = ________;
在强制四字节对齐情况下,请指出sizeof(HEAD_S) = ________;
答案:10 10 12
11.union tagAAAA
{
struct
{
char ucFirst;
short usSecond;
char ucThird;
}half;
long lI;
}number;
struct tagBBBBB
{
char ucFirst;
short usSecond;
char ucThird;
short usForth;
}half;
struct tagCCCC
{
struct
{
char ucFirst;
short usSecond;
char ucThird;
}half;
long lI;
};
在字节对齐为1下,sizeof(uniontagAAAA)、sizeof(struct tagBBBBB)、sizeof(struct tagCCCC)是____ ____ _____
在字节对齐为4下,sizeof(uniontagAAAA)、sizeof(struct tagBBBBB)、sizeof(struct tagCCCC)是____ ____ _____
答案:4 6 8
8 8 12
12.struct tagABC
{
char cB;
short sC;
char cD;
long lA;
}*pAbc;
pAbc = 0x100000;
那么pAbc+0x100 = 0x_________; (ULONG)pAbc + 0x100 = 0x_________;(ULONG *)pAbc + 0x100 = 0x_________;(char *)pAbc + 0x100
= 0x_______;
答案:100C00 100100 100400 100100
14.下面的代码中,函数Test执行完毕后,打印的结果是 _____。
unsigned long g_ulGlobal = 0;
void GlobalInit(unsigned long ulArg)
{
ulArg = 0x01;
return;
}
void Test()
{
GlobalInit(g_ulGlobal);
printf("%lu", g_ulGlobal);
return;
}
答案:0
16.以下程序的输出的结果是___________
#pragma pack(4)/*四字节对齐*/
int main(int argc, char* argv[])
{
unsigned char puc[4];
struct tagPIM
{
unsigned char ucPim1;
unsigned char ucData0:1;
unsigned char ucData1:2;
unsigned char ucData2:3;
}*pstPimData;
pstPimData = (struct tagPIM *)puc;
memset(puc, 0, 4); //全部置0。(初始化puc,每一位初始化为0,块大小为4)
pstPimData->ucPim1 = 1;
pstPimData->ucData0 = 2;
pstPimData->ucData1 = 3;
pstPimData->ucData2 = 4;
printf("%02X %02X %02X %02X/n", puc[0], puc[1], puc[2], puc[3]);
return 0;
}
#pragma pack()/*恢复缺省对齐方式*/
答案:01 26 00 00
Q1,4字节对齐下char是否还是1字节?
Q2,pstPimData共占多少字节内存,即sizeof(pstPimData)的大小,ucPim1 占1个字节,后面三个变量共占1个字节,是这样吗??
解释 :上面那个叫做位结构,就是以二进制位为存储单元的。
memset(puc, 0, 4);
pstPimData->ucPim1 = 1;
pstPimData->ucData0 = 2;
pstPimData->ucData1 = 3;
pstPimData->ucData2 = 4;
由于ucData0的大小是1比特,赋值为2产生了溢出,保留低位是0。
赋值以后的内存数据理论上应该是这样的(二进制):
0000 0001 0111 0000 0000 0000 0000 0000
第一字节--第二字节--第三字节--第四字节
但是,在Intel CPU中,使用的小尾字节序,所以内存中的二进制实际上是:
1000 0000 0110 0100 0000 0000 0000 0000
第一字节--第二字节--第三字节--第四字节
即将每次赋值的数都会把二进制反转过来。
0000 0001 变成了 1000 0000
100 变成了 001
当按照unsigned char大小读出来时,CPU会对每个字节再反转过来解释,因此每个字节的二进制值分别是:
第一字节:0000 0001 = 0x01
第二字节:0010 0110 = 0x26(这里是十六进制,每四位二进制数为一位十六进制数)
第三字节及第四字节都是0
好了,解释的够全面了吧?ref here
注意:
1. 溢出,保留低位;
2. 第一次反转,是赋值存储时的反转,规则是按照每个变量定义的位数反转;第二次反转,是读取访问时的反转,按照整1ge字节读取,则是整个字节反转。
上面方法解释的繁琐了,这样更好理解,因为是小端(LittleEndian)方式存储,所以按照小端的方式来,即高位在高位,低位在低位,于是有:
ucData0是1比特,赋值2,保留低位0,放在高位;
ucData1是2比特,赋值3,保留低位11,继续放在高位,即ucData0的1比特位置前面;
ucData2是3比特,赋值4,二进制刚好3位100,继续放在高位,即ucData1的2比特的前面;
这样1字节8位还剩两位,补0,最后也就是00 100 11 0,对应的十六进制为:0X26。
ref here
补充一下额外知识点:
void *memset(void *s, int ch, unsigned n);
函数解释:将s中当前位置后面的n个字节 (typedef unsigned int size_t )用 ch 替换并返回 s 。即,将s所指向的某一块内存中的每个字节的内容全部设置为ch指定的ASCII值, 块的大小由第三个参数指定, 这个函数通常为新申请的内存做初始化工作, 其返回值为指向S的指针。
memset:作用是在一段内存块中填充某个给定的值,它是对较大的结构体或数组进行清零操作的一种最快方法。
Notes :
1. 一定要记住如果要把一个char a[20]清零,一定是 memset(a,0,20*sizeof(char));
2.一个例子
1
2
3
4
5
6
7
8
9
10
11
12
|
#include <string.h>
#include <stdio.h>
#include <memory.h>
int
main(
void
)
{
char
buffer[]=
"Helloworld\n"
;
printf
(
"Buffer before memset:%s\n"
,buffer);
memset
(buffer,
'*'
,
strlen
(buffer));
printf
(
"Buffer after memset:%s\n"
,buffer);
return
0;
}
|
1
2
3
|
Buffer before memset:Helloworld
Buffer after memset:***********
|
比如上例中可以这样:
memset
(buffer,3
,
strlen
(buffer));
%02X :
以十六进制长度为2的形式输出
02 表示不足两位,前面补0输出;出过两位,不影响
举例:
printf("%02X", 0x123); //打印出:123
printf("%02X", 0x1); //打印出:01
补充一下,%02X会格式化为大写,%02x会格式化为小写;%2x,不足两位也不补0.
19.UCHAR *pucCharArray[10][10];
typedef union unRec
{
ULONG ulIndex;
USHORT usLevel[6];
UCHAR ucPos;
}REC_S;
REC_S stMax,*pstMax;
四字节对齐方式时: sizeof(pucCharArray) = ______, sizeof(stMax)=_______, sizeof(pstMax)=________,sizeof(*pstMax)=________.
答案:400(4*10*10) 12 4 12
Q1,联合体内各个成员变量分别占多少字节?(USHORT usLevel[6]占多少?一个USHORT不就2个了吗?)unRec占多少?
分别占4,12,1;unRec占12。//联合 成员共享内存,取最大的
Q2, sizeof(pucCharArray) 为400,是因为pucCharArray是指针而占4个字节的吗?20.typedef union unHead
{
UCHAR aucSrc [6];
struct tagContent
{
UCHAR ucFlag[3];
ULONG ulNext;
}Content;
}HEAD_S;
32CPU,VC编译环境下:
在强制一字节对齐情况下,请指出sizeof(HEAD_S) = ________;
在强制二字节对齐情况下,请指出sizeof(HEAD_S) = ________;
在强制四字节对齐情况下,请指出sizeof(HEAD_S) = ________;
答案:7 8 8
22. struct BBB
{
long lNum;
char *pcName;
short sDate;
char cHa[2];
short sBa[6];
}*p;
p = 0x100000;
p + 0x1 = 0x____
(unsigned long)p + 0x1 = 0x______
(unsigned long *)p + 0x1 = 0x______
(char *)p + 0x1 = 0x______
答案:100018 100001 100004 100001
23.在4字节对齐的情况:
typedef struct tagRec
{
long lA1;
char cA2;
char cA3;
long lA4;
long lA5;
} REC_S;
void main(int argc, char *argv[])
{
REC_S stMax ;
printf("/r/n sizeof(stMax)= %d",sizeof(stMax));
return;
}
输出结果为:
sizeof(stMax)=____
答案:16
24.void main ()
{
unsigned long ulA = 0x11000000;
printf("/r/n%x",*(unsigned char *)&ulA);
return;
}
输出结果为:
答案:0
其实就是考的你,unsigned long ulA在内存怎么存储
由于采用小数端存储,所以内存中为:
00 00 00 11
(unsigned char *)&ulA指向第一位,所以为0
扩展一下,和本题无关
举个例子如下
struct test_s
{
unsigned char a;
int b;
};
struct test_s s;
s.a='a';
printf("a=%c\n",s.a);
printf("a=%c\n",*(unsigned char *)&s); //两个printf打印的结果都是一样的
这里 &s为 struct test_s * 类型指针
强制类型转化为unsigned char *
再取unsigned char *指针对应的值,结构体struct test_s第一个元素就是unsigned char类型
所以*(unsigned char *)&s 就对应元素s.a