嵌入式软件基础问题-转

  1. volatile关键字的作用

直译为“易变”,与const相反。用volatile定义的变量,在每一次被访问时都是从内存中读取该量的值,volatile不允许编译器优化该值到寄存器,所以取值时不从寄存器中读取缓存。

作用在于可以获取变量的最新值、实时值,避免读到脏数,保证了变量的可见性(visibility)。

在多个线程中操作的值可以用volatile修饰,如果该值变化,其他线程可以得到最新值。在中断中可能会随时改变的值可以用volatile定义。另外寄存器的值也可以用volatile定义,保证对寄存器值的稳定访问。

详细理解需要明白编译器的优化过程
详解: C语言再学习 – 关键字volatile_不积跬步,无以至千里-CSDN博客

  1. 全局变量与局部变量的区别与作用

存储的内存区域不同,全局变量存在全局区,局部变量存于栈中。

作用域不同,全局变量如果加static关键字,则作用域在本源文件中,如果不加static关键字,则默认为extern,可作用于整个项目的所有文档。局部变量作用域在函数内部,函数返回后就会被自动释放。

  1. 全局变量和局部变量能否同名?

可以编译通过,但可能导致错误。

在局部变量的作用域内,若有变量与全局变量同名,则默认是当作局部变量处理(局部屏蔽全局)。实际编写代码时会避免同名问题。

  1. 什么是预编译?有哪些预编译指令?

预编译是在编译期间执行的文本替换。

预编译的指令包括#if #else #elif #endif #include #ifdef #ifndef等。

详解: 条件编译/条件宏定义_Electrical_IT的博客-CSDN博客

  1. static关键字的作用

若修饰全局变量,则作用域在该源文件.c中,若变量在.c中的多个函数中共同使用,就可以用静态全局变量。
若修饰局部变量,则作用域在函数体内,若希望函数体内有变量不在函数结束时释放,就用static修饰,下一次执行函数体时,变量的值仍保留,初始化只进行一次。因为静态局部变量存储与内存中的全局区,所以不会因为函数结束被释放。
若修饰函数,则作用域在该源文件,可以用于只在源文件被调用的函数,防止同项目的其他.c文件调用。

  1. 用一个宏来表示一年中有多少秒(笔试:考察宏的写法是否简介、明了、严谨。)
#define SECONDS_PER_YEAR (60*60*24*365)UL

   
   
  • 1

注意:UL表示无符号长整型常数

  1. 为一个绝对地址为0x8877的整型变量赋值为0x7788

一行代码实现:

*(int *const)(0x8877) = 0x7788;

   
   
  • 1

三行代码实现:

int *p;
p = (int*)0x8877;
*p = 0x7788;

   
   
  • 1
  • 2
  • 3
  1. 用C语言写一个strcpy()函数
    (考察C语言基本点:指针)
// 错误示范!!!
int strcpy(char *str1, char* str2)
{
	if(str2 != NULL)
	{
		for(int i=0;i<strlen(str2);i++)
		{
			str1[i] = str2[i];
		}
		str2[i] = '\0';
		return 0;
	}
	return 1;
}

   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
// 正确答案

// 写法一:
char mystrcpy(char des, const char src)
{
char ret=des; //将目标地址赋给ret,返回ret地址
while (src != ‘\0’ ) //当src不为结尾时,循环将src的字符赋给des
{
des = src;
des++;
src++;
}
des = ‘\0’; //给des加上’\0’结尾
return ret;

}

// 写法二:
char mystrcpy(char des, const char src)
{
char ret = des;
while ((des++) = (src++));
return ret;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

来源:C语言实现strcpy()函数_Kobe1916的博客-CSDN博客

  1. 用C语言写一个宏函数,得到两个参数值的最小值
#define MIN(a,b) ((a)<(b)? (a):(b))

 
 
  • 1

注意:函数部分所有参数都要加括号,因为宏定义只是文本替换,加括号才能保证优先级不会错误。

  1. 用C语言写一个宏函数,交换两个参数的值
#define SWAP(a,b) ((a)=(a)+(b);(b)=(a)-(b);(a)=(a)-(b);)

 
 
  • 1

注意:不用新变量即可完成交换

  1. 已知数组apple[],用宏表示数组元素的个数
#define ELEMENTS(A) (sizeof(A)/sizeof(A[0]))

 
 
  • 1

注意:sizeof()为库函数,计算所占字节数,包括\0

sizeof详解: C语言 sizeof函数详解_C_peter的博客-CSDN博客

  1. C/C++程序在编译后,内存中是如何分布的?

代码区(text/Code)、已初始化的全局变量区(data/GVAR——global value)、未初始化的全局变量区(bss)、堆区(heap)、栈区(stack) 从低地址到高地址排列。
不同区的作用不同,地址不同。

  • 栈区:主要用来存放局部变量, 传递参数, 存放函数的返回地址。.esp 始终指向栈顶, 栈中的数据越多, esp的值越小。

  • 堆区:用于存放动态分配的对象, 当你使用 malloc和new 等进行分配时,所得到的空间就在堆中。动态分配得到的内存区域附带有分配信息, 所以你能够 free和delete它们。

  • 数据区:全局,静态和常量是分配在数据区中的,数据区包括bss(未初始化数据区)和初始化数据区。

堆向高内存地址生长。
栈向低内存地址生长,随着函数调用层数的增加,函数栈帧是一块块地向内存低地址方向延伸的;随着进程中函数调用层数的减少(即各函数调用的返回),栈帧会一块块地被遗弃而向内存的高址方向回缩。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值