以下每个标题即为题目,可以自行作答后,点击标题查看答案。
文章目录
volatile关键字的作用
直译为“易变”,与const相反。用volatile定义的变量,在每一次被访问时都是从内存中读取该量的值,volatile不允许编译器优化该值到寄存器,所以取值时不从寄存器中读取缓存。
作用在于可以获取变量的最新值、实时值,避免读到脏数,保证了变量的可见性(visibility)。
在多个线程中操作的值可以用volatile修饰,如果该值变化,其他线程可以得到最新值。在中断中可能会随时改变的值可以用volatile定义。另外寄存器的值也可以用volatile定义,保证对寄存器值的稳定访问。
详细理解需要明白编译器的优化过程。
详解: C语言再学习 – 关键字volatile_不积跬步,无以至千里-CSDN博客
全局变量与局部变量的区别与作用
存储的内存区域不同,全局变量存在全局区,局部变量存于栈中。
作用域不同,全局变量如果加static关键字,则作用域在本源文件中,如果不加static关键字,则默认为extern,可作用于整个项目的所有文档。局部变量作用域在函数内部,函数返回后就会被自动释放。
全局变量和局部变量能否同名?
可以编译通过,但可能导致错误。
在局部变量的作用域内,若有变量与全局变量同名,则默认是当作局部变量处理(局部屏蔽全局)。实际编写代码时会避免同名问题。
什么是预编译?有哪些预编译指令?
预编译是在编译期间执行的文本替换。
预编译的指令包括#if #else #elif #endif #include #ifdef #ifndef等。
详解: 条件编译/条件宏定义_Electrical_IT的博客-CSDN博客
static关键字的作用
若修饰全局变量,则作用域在该源文件.c中,若变量在.c中的多个函数中共同使用,就可以用静态全局变量。
若修饰局部变量,则作用域在函数体内,若希望函数体内有变量不在函数结束时释放,就用static修饰,下一次执行函数体时,变量的值仍保留,初始化只进行一次。因为静态局部变量存储与内存中的全局区,所以不会因为函数结束被释放。
若修饰函数,则作用域在该源文件,可以用于只在源文件被调用的函数,防止同项目的其他.c文件调用。
用一个宏来表示一年中有多少秒(笔试:考察宏的写法是否简介、明了、严谨。)
#define SECONDS_PER_YEAR (60*60*24*365)UL
注意:UL表示无符号长整型常数
为一个绝对地址为0x8877的整型变量赋值为0x7788
一行代码实现:
*(int *const)(0x8877) = 0x7788;
三行代码实现:
int *p;
p = (int*)0x8877;
*p = 0x7788;
用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;
}
// 正确答案
// 写法一:
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;
}
来源:C语言实现strcpy()函数_Kobe1916的博客-CSDN博客
用C语言写一个宏函数,得到两个参数值的最小值
#define MIN(a,b) ((a)<(b)? (a):(b))
注意:函数部分所有参数都要加括号,因为宏定义只是文本替换,加括号才能保证优先级不会错误。
用C语言写一个宏函数,交换两个参数的值
#define SWAP(a,b) ((a)=(a)+(b);(b)=(a)-(b);(a)=(a)-(b);)
注意:不用新变量即可完成交换
已知数组apple[],用宏表示数组元素的个数
#define ELEMENTS(A) (sizeof(A)/sizeof(A[0]))
注意:sizeof()为库函数,计算所占字节数,包括\0
sizeof详解: C语言 sizeof函数详解_C_peter的博客-CSDN博客
C/C++程序在编译后,内存中是如何分布的?
代码区(text/Code)、已初始化的全局变量区(data/GVAR——global value)、未初始化的全局变量区(bss)、堆区(heap)、栈区(stack) 从低地址到高地址排列。
不同区的作用不同,地址不同。
-
栈区:主要用来存放局部变量, 传递参数, 存放函数的返回地址。.esp 始终指向栈顶, 栈中的数据越多, esp的值越小。
-
堆区:用于存放动态分配的对象, 当你使用 malloc和new 等进行分配时,所得到的空间就在堆中。动态分配得到的内存区域附带有分配信息, 所以你能够 free和delete它们。
-
数据区:全局,静态和常量是分配在数据区中的,数据区包括bss(未初始化数据区)和初始化数据区。
堆向高内存地址生长。
栈向低内存地址生长,随着函数调用层数的增加,函数栈帧是一块块地向内存低地址方向延伸的;随着进程中函数调用层数的减少(即各函数调用的返回),栈帧会一块块地被遗弃而向内存的高址方向回缩。