1.2 嵌入式八股文(二)

一、关键字

C语言宏中"#“”##"的用法

1. #)字符串化操作符

作用:将宏定义中的传入参数名转换成用一对双引号括起来参数名字符串。其只能用于有传入参数的宏

定义中,且必须置于宏定义体中的参数名前。

如:

#define example( instr ) printf( "the input string is:\t%s\n", #instr )

#define example1( instr ) #instr当使用该宏定义时:

example( abc ); // 在编译时将会展开成:printf("the input string is:\t%s\n","abc")

string str = example1( abc ); // 将会展成:string str="abc"

2. ##)符号连接操作符

作用:将宏定义的多个形参转换成一个实际参数名。

如:

#define exampleNum( n ) num##n

使用:

int num9 = 9;

int num = exampleNum( 9 ); // 将会扩展成 int num = num9

注意

a. 当用##连接形参时,##前后的空格可有可无。

如:

#define exampleNum( n ) num ## n // 相当于 #define exampleNum( n ) num##n

b. 连接后的实际参数名,必须为实际存在的参数名或是编译器已知的宏定义。

c. 如果##后的参数本身也是一个宏的话,##会阻止这个宏的展开。


二、strlen("\0") =sizeof("\0")=?

strlen("\0") =0,sizeof("\0")=2。

strlen用来计算字符串的长度(在C/C++中,字符串是以"\0"作为结束符的),它从内存的某个位置(可以是字符串开头,中间某个位置,甚至是某个不确定的内存区域)开始扫描直到碰到第一个字符串结束符\0为止,然后返回计数器值sizeof是C语言的关键字,它以字节的形式给出了其操作数的存储大小,操作数可以是一个表达式或括在括号内的类型名,操作数的存储大小由操作数的类型决定。


三、sizeofstrlen有什么区别?

strlen与sizeof的差别表现在以下5个方面。

1. sizeof是运算符(是不是被弄糊涂了?事实上,sizeof既是关键字,也是运算符,但不是函数),而strlen是函数。sizeof后如果是类型,则必须加括弧,如果是变量名,则可以不加括弧。

2. sizeof运算符的结果类型是size_t,它在头文件中typedef为unsigned int类型。该类型保证能够容纳实现所建立的最大对象的字节大小

3. sizeof可以用类型作为参数,strlen只能用char*作参数,而且必须是以“0结尾的。sizeof还可以以函数作为参数,如int g(),则sizeof(g())的值等于sizeof(int的值,在32位计算机下,该值为4。

4. 大部分编译程序的sizeof都是在编译的时候计算的,所以可以通过sizeof(x)来定义数组维数。而strlen则是在运行期计算的,用来计算字符串的实际长度,不是类型占内存的大小。例如,char str[20] = "0123456789”,字符数组str是编译期大小已经固定的数组,在32位机器下,为sizeof(char)*20=20,而其strlen大小则是在运行期确定的,所以其值为字符串的实际长度10。

5. 当数组作为参数传给函数时,传递的是指针,而不是数组,即传递的是数组的首地址。

四、C语言中structunion的区别是什么?

struct(结构体)与union(联合体)是C语言中两种不同的数据结构,两者都是常见的复合结构,其区别主要表现在以下两个方面。

1. 结构体与联合体虽然都是由多个不同的数据类型成员组成的,但不同之处在于联合体中所有成员用一块地址空间,即联合体只存放了一个被选中的成员,而结构体中所有成员占用空间是累加的,其所有成员都存在,不同成员会存放在不同的地址。在计算一个结构型变量的总长度时,其内存空间大小等于所有成员长度之和(需要考虑字节对齐),而在联合体中,所有成员不能同时占用内存空间,它们不能同时存在,所以一个联合型变量的长度等于其最长的成员的长度

2. 对于联合体的不同成员赋值,将会对它的其他成员重写,原来成员的值就不存在了,而对结构体的不同成员赋值是互不影响的。

typedef union {double i; int k[5]; char c;}DATE;
typedef struct data( int cat; DATE cow;double dog;)too;
DATE max;
printf ("%d", sizeof(too)+sizeof(max));

假设为32位机器,int型占4个字节,double型占8个字节,char型占1个字节,而DATE是一个联合型变量,联合型变量共用空间,uion里面最大的变量类型是int[5],所以占用20个字节,它的大小是20,而由于union中double占了8个字节,因此union是要8个字节对齐,所占内存空间为8的倍数。为了实现8个字节对齐,所占空间为24.而data是一个结构体变量,每个变量分开占用空间,依次为sizeof(int)+ sizeof(DATE)+ sizeof(double)=4+24+8=36按照8字节对齐,占用空间为40,所以结果为40+24=64。


、inline函数

在C语言中,如果一些函数被频繁调用,不断地有函数入栈,即函数栈,会造成栈空间或栈内存的大量消耗。为了解决这个问题,特别的引入了inline修饰符,表示为内联函数。

大多数的机器上,调用函数都要做很多工作:调用前要先保存寄存器,并在返回时恢复,复制实参,程序还必须转向一个新位置执行C++中支持内联函数,其目的是为了提高函数的执行效率,用关键字 inline放在函数定义(注意是定义而非声明)的前面即可将函数指定为内联函数,内联函数通常就是将它在程序中的每个调用点上“内联地”展开。

内联是以代码膨胀(复制)为代价,仅仅省去了函数调用的开销,从而提高函数的执行效率。


六、用变量a给出下面的定义

    a) 一个整型数;
    b)一个指向整型数的指针;
	c)一个指向指针的指针,它指向的指针是指向一个整型数;
	d)一个有10个整型的数组;
	e)一个有10个指针的数组,该指针是指向一个整型数;
	f)一个指向有10个整型数数组的指针;
	g)一个指向函数的指针,该函数有一个整型参数并返回一个整型数;
	h)一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数
	答案:
	a)int a
	b)int *a;
	c)int **a;
	d)int a[10];
	e)int *a [10];
	f) int a[10], *p=a;
	g)int (*a)(int)
	h) int( *a[10])(int)
	

七、左值和右值是什么?

左值是指可以出现在等号左边的变量或表达式,它最重要的特点就是可写(可寻址)。也就是说,它的值可以被修改,如果一个变量或表达式的值不能被修改,那么它就不能作为左值。右值是指只可以出现在等号右边的变量或表达式。它最重要的特点是可读。一般的使用场景都是把一个右值赋值给一个左值。通常,左值可以作为右值,但是右值不一定是左值。

什么是短路求值?

#include <stdio.h>
int main()
 {
    int i = 6;
    int j = 1;
    if(i>0||(j++)>0);
    printf("%D\r\n",j);
    return 0;
 }

输出结果为1。

输出为什么不是2,而是1呢?其实,这里就涉及一个短路计算的问题。由于i语句是个条件判断语句,里面是有两个简单语句进行或运算组合的复合语句,因为或运算中,只要参与或运算的两个表达式的值都为真,则整个运算结果为真,而由于变量i的值为6,已经大于0了,而该语句已经为true,所以后续的j++操作不需要执行,j的值仍然为1。

因为短路计算的问题,对于&&操作,由于在两个表达式的返回值中,如果有一个为假则整个表达式的值都为假,如果前一个语句的返回值为false,则无论后一个语句的返回值是真是假,整个条件判断都为假,不用执行后一个语句,而a>b的返回值为false,程序不执行表达式n=c>d,所以,n的值保持为初值2。


八、++aa++有什么区别?两者是如何实现的?

a++的具体运算过程为

1 int temp = a;

2 a=a+1;

3 return temp;

++a的具体运算过程为

1 a=a+1;

2 return a;

后置自增运算符需要把原来变量的值复制到一个临时的存储空间,等运算结束后才会返回这个临时变量的值。所以前置自增运算符效率比后置自增要高。


九、C++的内存管理是怎样的?

在C++中,虚拟内存分为代码段、数据段、BSS段、堆区、文件映射区以及栈区六部分。

代码段:包括只读存储区和文本区,其中只读存储区存储字符串常量,文本区存储程序的机器代码。

数据段:存储程序中已初始化的全局变量和静态变量。

BSS :存储未初始化的全局变量和静态变量(局部+全局),以及所有被初始化为0的全局变量和静态变量。

堆区:调用new/malloc函数时在堆区动态分配内存,同时需要调用delete/free来手动释放申请的内存。

映射区:存储动态链接库以及调用mmap函数进行的文件映射。

:使用栈空间存储函数的返回地址、参数、局部变量、返回值。


 

  • 28
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
嵌入式C语言八股文是指在嵌入式系统开发中常见的基本知识点和技能要求的简要总结。下面是嵌入式C语言八股文的主要内容: 1. 数据类型:包括基本数据类型(如int、char、float等)和派生数据类型(如数组、结构体、枚举等),掌握各种数据类型的使用方法和特点。 2. 运算符:熟悉各种算术运算符、逻辑运算符、位运算符等,掌握它们的优先级和结合性,能够正确使用运算符完成各种计算任务。 3. 控制语句:包括条件语句(if-else语句)、循环语句(for、while、do-while循环)、选择语句(switch-case语句)等,掌握这些语句的使用方法和注意事项。 4. 函数:了解函数的定义和调用,能够编写函数并正确使用函数参数和返回值,理解函数的作用域和生命周期。 5. 数组和指针:掌握数组和指针的定义和使用,了解数组和指针在内存中的存储方式,能够通过指针进行数组的访问和操作。 6. 文件操作:了解文件操作的基本流程,包括文件的打开、读写和关闭,理解文件指针和文件访问模式的概念。 7. 中断处理:了解中断的基本概念和原理,能够编写中断服务程序(ISR)并正确处理中断请求。 8. 程序调试:掌握常用的调试技巧和工具,能够使用调试器进行程序的单步执行、观察变量值等操作,能够分析程序运行过程中的错误和异常。 以上是嵌入式C语言八股文的主要内容,掌握这些知识和技能,可以帮助你在嵌入式系统开发中更好地应对各种任务和挑战。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嵌入式&机器人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值