持续更新版本 嵌入式工程师常见面试题( 六 )


11、 作用和用法
是一个修饰符,用于声明在多线程环境下可能会被意外修改的变量 。
在多线程环境下,由于有多个线程同时访问共享变量,可能会导致一些意外的行为,如一个线程正在修改变量时,另一个线程正在读取该变量,读取到的值可能不是最新的值 。这种情况下,就需要使用关键字来确保变量的可见性和一致性 。
具体来说,使用关键字可以保证以下几点:
保证变量的可见性:当一个线程修改变量的值时,其他线程会立即看到这个最新的值 。
防止指令重排:由于编译器可能会对代码进行优化,导致一些指令的执行顺序与代码中的顺序不一致 。使用关键字可以防止这种指令重排,确保代码的执行顺序与代码中的顺序一致 。
需要注意的是,虽然使用关键字可以保证变量的可见性和一致性,但它不能保证线程之间的同步 。如果需要保证线程之间的同步,还需要使用其他的同步机制 。
12、变量的作用域(全局变量和局部变量)
变量的作用域是指变量在程序中可以使用的范围 。在C/C++中,变量可以分为全局变量和局部变量两种 。
全局变量( ):
全局变量是在函数外部定义的变量,它们的作用域是整个程序,可以从头文件一直使用到程序结束 。全局变量通常在程序启动时初始化,并且可以被程序中的多个函数共同使用 。局部变量(local ):
局部变量是在函数内部定义的变量,它们的作用域仅限于函数内部 。当函数执行结束时,局部变量会被销毁,其内存空间也会被释放 。
13、 与(字符串,数组)
() 是 C/C++ 中的运算符,用于获取变量或数据类型在内存中所占用的字节数 。而 () 是 C/C++ 中的函数,用于计算字符串的长度(不包括字符串结束符 '\0') 。
对于字符串和数组,() 和 () 的使用有以下区别:
字符串:
数组:
需要注意的是,() 运算符的结果是一个编译时确定的常量表达式,而 () 函数需要在运行时逐个字符地计算字符串的长度 。在使用时需要根据具体情况选择合适的函数,并注意避免越界访问和空指针异常等问题 。
14、经典的()和内存对齐(一字节对齐)
在C语言中,()运算符用于获取变量或数据类型的大小 。对于类型,()运算符将返回整个的大小,而不是每个成员变量的大小之和 。这是因为C语言中的成员变量的对齐方式可能会导致的大小不是成员变量大小的整数倍 。
内存对齐是为了提高内存访问的效率而引入的一种内存布局技术 。在32位系统中最小的对齐单位是4字节,在64位系统中最小的对齐单位是8字节 。根据对齐单位,编译器会在变量或结构体成员之间插入填充字节,使得它们的起始地址满足对齐要求 。
对于一字节对齐,它通常用于一些特定的数据类型,例如char类型,它占用的空间就是1个字节 。对于一些需要按照字节进行访问的数据类型,例如位域(bit-),也需要使用一字节对齐来保证数据的正确性 。
在使用()运算符时,需要注意以下几点:

持续更新版本  嵌入式工程师常见面试题

文章插图
对于结构体或联合体类型,()返回的大小是整个结构体或联合体的占据的内存空间,而不是每个成员变量的大小之和 。在进行内存对齐时,需要考虑结构体成员变量的类型、大小和顺序,以及编译器和系统的对齐要求 。合理地规划内存布局可以提高程序的性能和效率 。对于一些特殊的对齐要求,例如一字节对齐,需要使用特定的语法或技巧来实现,例如使用# pack指令或者在结构体中使用特定的对齐修饰符(如(()) 。