#error的作用是什么?
#error 指令让预处理器发出一条错误信息,并且会中断编译过程。下面我们从linux代码中抽取出来一小段代码并做修改得到示例代码:
这段示例代码很简单,当rx_buf_idx宏的值不为0~3时,在预处理阶段就会通过 #error 指令输出一条错误提示信息:
invalid configuration for 8139_rxbuf_idx 下面编译看一看结果:
位操作的基本使用
给一个32bit数据的位置1,怎么用宏来实现?
#define set_bit(x, bit) (x |= (1 < 6) printf(a+b大于6); else printf(a+b小于6); return 0;} 程序输出结果为:a+b大于6 原因是因为编译器会将有符号数b转换成为一个无符号数,即此处 a+b 等价于 a+(unsigned int)b 。 该程序运行在32bit环境下,b的值为 0xffffffff-20+1 = 4294967276 ,即a+b将远远大于6。 c 语言按照一定的规则来进行此类运算的转换,这种规则称为 正常算术转换 ,转换的顺序为:double>float>unsigned long>long>unsigned int>int 即操作数类型排在后面的与操作数类型排在前面的进行运算时,排在后面的类型将 隐式转换 为排在前面的类型。 typedef与define的区别
(1)#define之后不带分号,typedef之后带分号。 (2)#define可以使用其他类型说明符对宏类型名进行扩展,而 typedef 不能这样做。如:
#define int1 intunsigned int1 n; //没问题typedef int int2;unsigned int2 n; //有问题 int1可以使用类型说明符unsigned进行扩展,而int2不能使用unsigned进行扩展。 (3)在连续定义几个变量的时候,typedef 能够保证定义的所有变量均为同一类型,而 #define 则无法保证。如:#define pint1 int*;p_int1 p1,p2; //即int *p1,p2;typedet int* pint2;p_int2 p1,p2; //p1、p2 类型相同 pint1定义的p1与p2类型不同,即p1为指向整形的指针变量,p2为整形变量;pint2定义的p1与p2类型相同,即都是指向 int 类型的指针。 写一个max宏
#define max(x,y) ((x) > (y) ? (x) : (y)) 使用括号把参数括起来可以解决了运算符优先级带来的问题。这样的max宏基本可以满足日常使用,但是还有更严谨的高级写法。 感兴趣的可参考文章: https://www.zhaixue.cc/c-arm/c-arm-express.html 死循环
嵌入式系统中经常要用到无限循环,你怎么样用c编写死循环呢? (1)while
while(1) { } (2)forfor(;;) { } (3)gotoloop:…goto loop; static的作用 在c语言中,关键字static有三个明显的作用: 1、在函数体修饰变量 一个被声明为静态的变量在这一函数被调用过程中维持其值不变。 2、 在模块内(但在函数体外)修饰变量 一个被声明为静态的变量可以被模块内所用函数访问,但不能被模块外其它函数访问。它是一个本地的全局变量。 3、在模块内修饰函数 一个被声明为静态的函数只可被这一模块内的其它函数调用。那就是,这个函数被限制在声明它的模块的本地范围内使用。
const的作用
下面的声明都是什么意思:
const int a; int const a;const int *a;int * const a;int const * a const;前两个的作用是一样,a是一个常整型数。 第三个意味着a是一个指向常整型数的指针(也就是,整型数是不可修改的,但指针可以)。
第四个意思a是一个指向整型数的常指针(也就是说,指针指向的整型数是可以修改的,但指针是不可修改的)。
最后一个意味着a是一个指向常整型数的常指针(也就是说,指针指向的整型数是不可修改的,同时指针也是不可修改的)。
volatile的作用
以下内容来自百度百科: 一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子: 1). 并行设备的硬件寄存器(如:状态寄存器) 2). 一个中断服务子程序中会访问到的非自动变量(non-automatic variables) 3). 多线程应用中被几个任务共享的变量 回答不出这个问题的人是不会被雇佣的。我认为这是区分c程序员和嵌入式系统程序员的最基本的问题。嵌入式系统程序员经常同硬件、中断、rtos等等打交道,所用这些都要求volatile变量。不懂得volatile内容将会带来灾难。 假设被面试者正确地回答了这是问题(嗯,怀疑这否会是这样),我将稍微深究一下,看一下这家伙是不是直正懂得volatile完全的重要性。 1). 一个参数既可以是const还可以是volatile吗?解释为什么。 2). 一个指针可以是volatile 吗?解释为什么。 3). 下面的函数有什么错误:
int square(volatile int *ptr){ return *ptr * *ptr;} 下面是答案: 1). 是的。一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。 2). 是的。尽管这并不很常见。一个例子是当一个中服务子程序修该一个指向一个buffer的指针时。 3). 这段代码的有个恶作剧。这段代码的目的是用来返指针 *ptr 指向值的平方,但是,由于 *ptr 指向一个volatile型参数,编译器将产生类似下面的代码:int square(volatile int* &ptr)//这里参数应该申明为引用,不然函数体里只会使用副本,外部没法更改{ int a,b; a = *ptr; b = *ptr; return a*b;} 由于*ptr的值可能在两次取值语句之间发生改变,因此a和b可能是不同的。结果,这段代码可能返回的不是你所期望的平方值!正确的代码如下:long square(volatile int*ptr){ int a; a = *ptr; return a*a;} 变量定义 用变量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];g) int ( *a)(int);h) int ( *a[10])(int); 中断函数
中断是嵌入式系统中重要的组成部分,这导致了很多编译开发商提供一种扩展—让标准c支持中断。具代表事实是,产生了一个新的关键字 __ interrupt 。 下面的代码就使用了 __ interrupt 关键字去定义了一个中断服务子程序(isr),请评论一下这段代码的。
新型嵌入式超声波测距系统[图]
电瓶修复技术——免费公开课开讲啦(铅酸电池不平衡连载1)
变压器有载自动调压控制系统详解
价格几乎一样!荣耀9、vivo x9s、努比亚Z17哪个比较好?荣耀9、vivo x9s、努比亚Z17区别对比评测
交流固态继电器的特点
嵌入式C语言经典的代码实例
Adam Taylor玩转MicroZed系列第76部分:关联布局宏的约束
ThinkPad BIOS设置手册
多家医院引入微信人脸识别技术 助力轻松挂号
中国联通与亨通集团宣布正式开通了京雄量子加密通信干线
Qualcomm和AT&T将在蜂窝网络环境下进行无人机试验,加速其大规模部署
X5045看门狗电路及其应用 (含源代码程序)
智慧停车的巨大潜力,它可能蕴含着一个千亿市场
机遇号:太阳系上最努力的探测工作者去世了
行业 | 欧航局发布无人机通用准则,明年6月起在正式启用
汽车的噪音源分析,以及如何抑制主噪音源
泛华贷款服务累计总额超500亿元,15万小微企业受益
非 CMOS 兼容的 SiC 功率器件在体硅晶圆厂中的制造
来自西安交大课件!《光电式传感器》
物联网设备面临的风险要比表面上看起来大得多