|
我是老温,一名热爱学习的嵌入式工程师- `% J; L" z& r
关注我,一起变得更加优秀!& D) R3 g/ ]6 b/ j* w, ~
在嵌入式软件开发领域,C 语言是一种功能强大、灵活的编程语言,它提供了很多语法特性,有些语法可能看起来比较"花里胡哨",用得好可能利大于弊,用不好,可能就是自己给自己挖坑。
" x. Y6 }$ o2 ?# Z7 x# M以下是一些可能被认为花哨的C语言特性及其示例:' I) C: j4 J+ E! m9 O6 J
1. 宏定义的高级用法
/ l3 [" M b- [; p7 |6 U( C7 |使用宏可以模拟函数的行为,但要注意宏的副作用和调试难度。#define SQUARE(x) ((x) * (x))int a = 5;printf("%d
- j: X4 }6 G# W1 {" s3 t", SQUARE(a++)); // 输出25,但a的值会改变为6
$ p: _$ a, W) L$ o( \7 c2. 指针的指针" f) R: h; {! H T& @2 T
指向指针的指针可以用于实现复杂的数据结构,比如二维数组。int **pptr;int arr[2][2] = {{1, 2}, {3, 4}};pptr = &arr[0];printf("%d
, A) o5 q( N R2 {) m7 H! R& R", *(*(pptr + 1) + 1)); // 输出44 Y9 Y; A- v6 c8 E0 B
3. 函数指针数组
$ s/ f' v ^/ E5 V数组中的每个元素都是指向函数的指针,这可以用于回调函数或实现简单的函数映射。void (*func_array[])(int) = {func1, func2, func3};func_array[1](42); // 调用func2
% ?8 K) H, f: r5 [) u; [5 b* S3 Z4. 结构体和联合体作为函数参数# x. z _/ b! Y0 Z
使用结构体或联合体作为函数参数可以传递复杂的数据结构。struct Point { int x, y;};) d9 k, i( |" E
void print_point(struct Point p) { printf("(%d, %d)! J* P% [/ p- T$ f/ f! V
", p.x, p.y);}
9 w/ \3 y3 i6 ^, {/ ?struct Point p = {1, 2};print_point(p);
/ f# {6 ]: N' `' {( Q5. 静态和动态内存分配6 o H- n2 m' B" K5 g4 o1 R
使用 “malloc” 和 “free” 可以动态地分配和释放内存。int *p = malloc(sizeof(int) * 10);5 ?% E0 U4 J( N0 \8 V
if (p) { for (int i = 0; i 10; i++) { p = i * i; } free(p);}6 x8 E q: L% `& v+ a8 y
6. 复杂的递归
) J" F4 ^/ Q8 a递归函数可以用于解决分治问题,但需要小心处理避免栈溢出。int factorial(int n){ if (n 1) return 1; return n * factorial(n - 1);}; c6 R$ u* g/ y* y* J+ b
7. 位操作
- }8 s+ D& ]3 g( b3 t位操作可以用于设置、清除、翻转、测试位的状态。int flags = 0x03; // 00000011flags |= 0x04; // 00000101flags &= 0x01; // 00000001flags ^= 0x01; // 11111110
' {, c0 k8 o- P% h8. 复杂的条件编译2 I: C8 k Z; A C* ~
预处理器的"#if"、"#ifdef"、"#ifndef"、"#elif"、"#else"和"#endif"指令可以用于复杂的条件编译。 #define DEBUG 1 int main() { #if DEBUG printf("Debug mode is on.$ {) U, Y! `5 s: {( |
"); #endif #ifdef DEBUG // 调试代码 #endif return 0; }
. g0 e, h: ]( u: w& w9 k9. 复杂的类型转换
; a. o! G" y/ ~7 H7 I强制类型转换可以用于将一种类型的数据转换为另一种类型,但需要小心使用以避免问题。double d = 3.14159;int *p = (int *)&d;printf("%d
5 B, O8 c* w# [( |! e", *p); // 输出整数部分,可能不安全
j6 H5 G2 D* Y& `10. 使用"__attribute__"扩展8 c# T6 P u8 E5 ]* e% b, z% G
"__attribute__"是GCC编译器提供的扩展,可以用来控制函数的调用约定、内联等。void __attribute__((noreturn)) fatal_error(const char *msg) { fprintf(stderr, "Fatal error: %s$ r1 h# X5 J( `* \/ u( Q, x
", msg); exit(EXIT_FAILURE);}+ P" j. F) J! p6 B" A8 o
这些特性在某些情况下非常有用,但它们也可能使代码难以理解和维护。因此,在使用这些特性时,应该权衡其利弊,并确保代码的清晰性和可读性。
8 D. W9 V; q, ~. U-END-
2 A8 ?* _% Z* i( n2 z; c- u6 e! U2 M往期推荐:点击图片即可跳转阅读: v" ?) F* n( x7 L8 P
' U9 D6 U j# z/ z# J
$ o5 f( J: X+ L- z# j 5 A8 E( a+ b' v4 I7 i
/ o8 P! K( p8 h. F2 W3 a
7 v9 M/ \1 t4 @; k( c/ }
jwz5q4xn5526408842600.jpg
7 g. i, H* {" c# I0 N- b1 c; W: y& I
- w) X& z2 {2 n, M9 ^7 v+ I
被 char 类型的变量坑惨了!: O; r! W/ }) q$ @
- G- j; Y. m4 O; N
( c* W7 N/ ~- {0 q
+ O* L5 r" A2 K, f; \4 Y& w o
/ A- F5 t) o V9 S/ l. R) N2 e
1f2of10ca0n6408842700.jpg
' I4 B4 g! k8 k* v. G, q4 ~3 }
( v* p" `! ?3 y 嵌入式 C 语言知识点,动态变长数组
: T+ g; T8 Y5 r% n0 K8 k
5 B/ e! b4 Q% t4 A( M
1 H$ x3 l2 I* B. X6 f9 D6 s
7 n. k4 `8 Y$ L! E . n2 ]" E1 R8 Q
zce0qcvyylb6408842800.jpg
6 U$ g+ m6 q" }, R+ x
( f5 z# \6 D( \9 ^: H% _( L: m" c, V 嵌入式 C 语言技巧,不完全类型
. `4 U. I+ g3 ~$ z* s, F+ f我是老温,一名热爱学习的嵌入式工程师
* X2 @1 S8 S0 ]; h8 h9 [0 N关注我,一起变得更加优秀! |
|