C 嵌入式面试题(一)
发布日期:2021-06-29 05:35:37 浏览次数:2 分类:技术文章

本文共 4811 字,大约阅读时间需要 16 分钟。

1:abcgak 值是什么?为什么?

struct potocal_t{

uint16_t a;
uint8_t b;
uint16_t c;
};
uint8_t msg[] ={0x1,0x2,3,4,5,6,7,8};
uint32_t abcgak =0;
abcgak =(uint32_t)(((struct potocal_t *)msg)->c);

abcgak =0x0605

原因:因为结构体占长度为,2+1+2=5;a地址 0x0000%4=0,b=0x0002%4=0;c =0x0004%4=0

2 .用预处理指令#define声明一个常数,用以表明1年中有多少秒(忽略闰年问

题)
#define SECONDS_PER_YEAR (60 * 60 * 24 *365)UL

3: const和volatile常考题

1).一个参数既可以是const还可以是volatile吗?解释为什么。
2).一个指针可以是volatile吗?解释为什么。
3).下面的函数有什么错误:
int square(volatile int *ptr)
{
return (*ptr) * (*ptr);
}

下面是答案:

1).是的。一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到
地改变。它是const因为程序不应该试图去修改它。
2).是的。尽管这并不很常见。一个例子是当一个中服务子程序修该一个指向一
个buffer的指针时。
3).这段代码的有个恶作剧。这段代码的目的是用来返指针ptr指向值的平方,
但是,由于
ptr指向一个volatile型参数

long square(volatile int *ptr)

{
int a;
a = *ptr;
return a * a;
}

4. 嵌入式系统总是要用户对变量或寄存器进行位操作。给定一个整型变量a,写

两段代码,第一个设置a的bit 3,
第二个清除a 的bit 3。在以上两个操作中,要保持其它位不变。

#define BIT3 (0x1<<3)

static int a;
void set_bit3(void)
{
a |= BIT3;
}
void clear_bit3(void)
{
a &= ~BIT3;
}

5.嵌入式系统经常具有要求程序员去访问某特定的内存位置的特点。在某工程

中,
要求设置一绝对地址为0x67a9的整型变量的值为0xaa66。编译器是一个纯粹的
ANSI编译器。写代码去完成这一任务。
这一问题测试你是否知道为了访问一绝对地址把一个整型数强制转换
(typecast)为一指针是合法的。
这一问题的实现方式随着个人风格不同而不同。典型的类似代码如下:
int *ptr;
ptr = (int *)0x67a9;
*ptr = 0xaa66;

6.下面的代码输出是什么,为什么?

Voidfoo(void)
{
unsigned int a = 6;
int b = -20;
(a+b > 6) ?puts(">6") : puts("<= 6");
}
C语言中的整数自动转换原则,我发现有些开发者懂得
极少这些东西。不管如何,
这无符号整型问题的答案是输出是“>6”。原因是当表达式中存在有符号类型和
无符号类型时所有的操作数都自动转换为无符号类型。
因此-20变成了一个非常大的正整数,所以该表达式计算出的结果大于6。
这一点对于应当频繁用到无符号数据类型的嵌入式系统来说是丰常重要的。如果
你答错了这个问题,你也就到了得不到这份工作的边缘。

7.评价下面的代码片断:

unsignedint zero = 0;
unsignedint compzero = 0XFFFF FFFF;
/*1’s complement of zero */
对于一个int型不是16位的处理器为说,上面的代码是不正确的。应编写如下:
unsigned int compzero = ~0;
这一问题真正能揭露出应试者是否懂得处理器字长的重要性。在我的经验里,好
的嵌入式程序员非常准确地明白硬件的细节和它的局限.

8.只算地址计算

unsignedchar *p1;
unsigned long *p2;
p1=(unsigned char *)0x801000;
p2=(unsigned long *)0x810000;
请问p1+5=? ;
p2+5=? ;
答:
p1+5=0x801005 ;
p2+5=0x810014 ;

9.不能做switch()的参数类型是:

switch的参数不能为实型。(只能是int char)

10.写出float x 与“零值”比较的if语句。

if(x<0.000001&&x>-0.000001)

11.全局变量和局部变量在内存中是否有区别?如果有,是什么区别?

全局变量储存在静态数据库,局部变量在栈

12.进程和线程的差别。

线程是指进程内的一个执行单元,也是进程内的可调度实体.

与进程的区别:

(1)调度:线程作为调度和分配的基本单位,进程作为拥有资源的基本单位

(2)并发性:不仅进程之间可以并发执行,同一个进程的多个线程之间也可并发执行
(3)拥有资源:进程是拥有资源的一个独立单位,线程不拥有系统资源,但可以访问隶属于进程的资源.
(4)系统开销:在创建或撤消进程时,由于系统都要为之分配和回收资源,导致系统的开销明显大于创建或撤消线程时的开销。

13. 以下代码中的两个sizeof用法有问题吗?

void UpperCase( char str[] ) // 将 str 中的小写字母转换成大写字母

{
for( size_t i=0; i<sizeof(str)/sizeof(str[0]); ++i )
if( ‘a’<=str[i] && str[i]<=‘z’ )
str[i] -= (‘a’-‘A’ );
}

char str[] = “aBcDe”;

cout << "str字符长度为: " << sizeof(str)/sizeof(str[0]) << endl;
UpperCase( str );
cout << str << endl;

答:函数内的sizeof有问题。根据语法,sizeof如用于数组,只能测出静态数组的大小,无法检测动态分配的或外部数组大小。函数外的str是一个静态定义的数组,因此其大小为6,函数内的str实际只是一个指向字符串的指针,没有任何额外的与数组相关的信息,因此sizeof作用于上只将其当指针看,一个指针为4个字节,因此返回4。

14.一个32位的机器,该机器的指针是多少位

指针是多少位只要看地址总线的位数就行了。80386以后的机子都是32的数据总线。所以指针的位数就是4个字节了。

main()
{
int a[5]={1,2,3,4,5};
int *ptr=(int *)(&a+1);

printf("%d,%d",*(a+1),*(ptr-1));

}

**(a+1)就是a[1],(ptr-1)就是a[4],执行结果是2,5

&a+1不是首地址+1,系统会认为加一个a数组的偏移,是偏移了一个数组的大小(本例是5个int)
int ptr=(int )(&a+1);
则ptr实际是&(a[5]),也就是a+5
输出:2,5

15 字符串常量

char* s=“AAA”;
printf("%s",s);
s[0]=‘B’;
printf("%s",s);
有什么错?

"AAA"是字符串常量。s是指针,指向这个字符串常量,所以声明s的时候就有问题。

cosnt char* s=“AAA”;
然后又因为是常量,所以对是s[0]的赋值操作是不合法的。

16.分析下面的程序

void GetMemory(char **p,int num)

{
*p=(char *)malloc(num);
}
int main()
{
char *str=NULL;
GetMemory(&str,100);
strcpy(str,“hello”);
free(str);
if(str!=NULL)
{
strcpy(str,“world”);
}
printf("\n str is %s",str);
getchar();
}

问输出结果是什么?希望大家能说说原因,先谢谢了

输出str is world。
free 只是释放的str指向的内存空间,它本身的值还是存在的.
所以free之后,有一个好的习惯就是将str=NULL.
此时str指向空间的内存已被回收,如果输出语句之前还存在分配空间的操作的话,这段存储空间是可能被重新分配给其他变量的,
尽管这段程序确实是存在大大的问题(上面各位已经说得很清楚了),但是通常会打印出world来。
这是因为,进程中的内存管理一般不是由操作系统完成的,而是由库函数自己完成的。
当你malloc一块内存的时候,管理库向操作系统申请一块空间(可能会比你申请的大一些),然后在这块空间中记录一些管理信息(一般是在你申请的内存前面一点),并将可用内存的地址返回。但是释放内存的时候,管理库通常都不会将内存还给操作系统,因此你是可以继续访问这块地址的

17 )给定结构struct A

{

char t:4;
char k:4;
unsigned short i:8;
unsigned long m;
};问sizeof(A) = ?
给定结构struct A

{

char t:4; 4位
char k:4; 4位
unsigned short i:8; 8位
unsigned long m; // 偏移2字节保证4字节对齐
}; // 共8字节

18 求结构体的大小

struct name1{
char str;
short x;
int num;
}
struct name2{
char str;
int num;
short x;
}
sizeof(struct name1)=8,sizeof(struct name2)=12

在第二个结构中,为保证num按四个字节对齐,char后必须留出3字节的空间;同时为保证整个结构的自然对齐(这里是4字节对齐),在x后还要补齐2个字节,这样就是12字节。



struct s1

{
int i: 8;
int j: 4;
int a: 3;
double b;
};
struct s2
{
int i: 8;
int j: 4;
double b;
int a:3;
};
printf(“sizeof(s1)= %d\n”, sizeof(s1));
printf(“sizeof(s2)= %d\n”, sizeof(s2));
result: 16, 24
第一个struct s1
{
int i: 8;
int j: 4;
int a: 3;
double b;
};
理论上是这样的,首先是i在相对0的位置,占8位一个字节,然后,j就在相对一个字节的位置,由于一个位置的字节数是4位的倍数,因此不用对齐,就放在那里了,然后是a,要在3位的倍数关系的位置上,因此要移一位,在15位的位置上放下,目前总共是18位,折算过来是2字节2位的样子,由于double是8字节的,因此要在相对0要是8个字节的位置上放下,因此从18位开始到8个字节之间的位置被忽略,直接放在8字节的位置了,因此,总共是16字节。

第二个最后会对照是不是结构体内最大数据的倍数,不是的话,会补成是最大数据的倍数

可以加入QQ群:687360507

与大伙沟通交流,技术在于分享而进步

转载地址:https://blog.csdn.net/zhi_Alanwu/article/details/104982773 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:CC26x2R1笔记(7)CCS9.2 CC26xx工程设置的环境变量
下一篇:mcu 内存分配

发表评论

最新留言

留言是一种美德,欢迎回访!
[***.207.175.100]2024年04月03日 12时13分35秒