Autosar 系列教程:小柴带你学 AutoSar 总目录

# 小柴带你学 AutoSar 系列一、基础知识篇(3)C 语言基础

# C 语言入门基本语法

C 语言是一种功能强大且高效的编程语言,被广泛应用于系统编程、嵌入式系统、游戏开发等领域。本文将介绍 C 语言的基本语法,并通过代码示例帮助你理解和掌握这些基础知识。

# 1. 程序结构

一个简单的 C 语言程序通常包含以下几个部分:

  • 预处理指令
  • 主函数
  • 变量声明
  • 语句和表达式

以下是一个简单的 C 语言程序示例:

#include <stdio.h>  // 预处理指令,包含标准输入输出库
int main() {  // 主函数
    printf("Hello, World!\n");  // 输出语句
    return 0;  // 返回值,0 表示程序成功结束
}

# 2. 变量和数据类型

C 语言支持多种数据类型,包括整型、浮点型、字符型等。常见的基本数据类型有:

  • int :整型
  • float :单精度浮点型
  • double :双精度浮点型
  • char :字符型

变量声明的示例如下:

int a;       // 整型变量
float b;     // 浮点型变量
double c;    // 双精度浮点型变量
char d;      // 字符型变量
a = 10;      // 赋值
b = 3.14f;   // 赋值
c = 2.718;   // 赋值
d = 'A';     // 赋值

# 3. 常量

常量是值在程序运行期间不可更改的数据。可以使用 const 关键字定义常量:

const int MAX_SIZE = 100;  // 整型常量
const float PI = 3.14159;  // 浮点型常量

# 4. 运算符

C 语言提供了多种运算符,包括算术运算符、关系运算符、逻辑运算符等。

  • 算术运算符: + , - , * , / , %
  • 关系运算符: == , != , > , < , >= , <=
  • 逻辑运算符: && , || , !

示例:

int x = 5, y = 3;
int sum = x + y;        // 算术运算
int diff = x - y;
int prod = x * y;
int quotient = x / y;
int remainder = x % y;
int isEqual = (x == y); // 关系运算
int isGreater = (x > y);
int andResult = (x > 0 && y > 0); // 逻辑运算
int orResult = (x > 0 || y < 0);
int notResult = !(x > 0);

# 5. 控制结构

# 条件语句

条件语句用于根据条件的真伪执行不同的代码块。

  • if 语句:
int number = 10;
if (number > 0) {
    printf("Number is positive\n");
} else if (number < 0) {
    printf("Number is negative\n");
} else {
    printf("Number is zero\n");
}
  • switch 语句:
char grade = 'B';
switch (grade) {
    case 'A':
        printf("Excellent\n");
        break;
    case 'B':
        printf("Good\n");
        break;
    case 'C':
        printf("Fair\n");
        break;
    case 'D':
        printf("Poor\n");
        break;
    default:
        printf("Invalid grade\n");
}

# 循环语句

循环语句用于重复执行某个代码块。

  • for 循环:
for (int i = 0; i < 5; i++) {
    printf("i = %d\n", i);
}
  • while 循环:
int count = 0;
while (count < 5) {
    printf("count = %d\n", count);
    count++;
}
  • do-while 循环:
int n = 0;
do {
    printf("n = %d\n", n);
    n++;
} while (n < 5);

# 6. 函数

函数是组织代码的基本单元,用于实现特定功能。函数可以有参数和返回值。

函数定义和调用示例如下:

#include <stdio.h>
int add(int a, int b) {  // 函数定义
    return a + b;
}
int main() {
    int result = add(5, 3);  // 函数调用
    printf("Result = %d\n", result);
    return 0;
}

# 7. 数组

数组是存储同类型数据的集合,可以通过下标访问数组元素。

数组声明和使用示例:

int numbers[5] = {1, 2, 3, 4, 5};  // 数组声明和初始化
for (int i = 0; i < 5; i++) {
    printf("numbers[%d] = %d\n", i, numbers[i]);
}

# 8. 指针

指针是存储变量地址的变量,可以通过指针访问和操作变量的值。

指针示例:

int x = 10;
int *p = &x;  // 指针 p 指向 x 的地址
printf("Value of x = %d\n", x);
printf("Address of x = %p\n", p);
printf("Value at address p = %d\n", *p);  // 通过指针访问 x 的值
函数返回值类型 (* 指针变量名) (函数参数列表);
typedef 函数返回值类型 (* 指针变量名) (函数参数列表);
typedef void (*pFun)(int x);
void myFun(int x)
{
    printf("myFun: %d\n",x);
}
pFun = myFun;// 函数指针指向 myFun (); 调用:pFun ();

# 9. 结构体

结构体是用户自定义的数据类型,用于存储不同类型的数据。

结构体定义和使用示例:

struct Student {
    int id;
    char name[50];
    float score;
};
struct Student student1;
student1.id = 1;
strcpy(student1.name, "John Doe");  // 字符数组赋值需要使用 strcpy 函数
student1.score = 95.5;
printf("ID: %d\n", student1.id);
printf("Name: %s\n", student1.name);
printf("Score: %.2f\n", student1.score);

# 10. 共用体

共用体(Union)是 C 语言中一种特殊的数据类型,它允许在相同的内存位置存储不同的数据类型。与结构体不同的是,共用体的所有成员共享同一块内存空间,因此共用体的大小等于其最大成员的大小。

# 共用体的定义

共用体通过关键字 union 来定义,其语法如下:

union UnionName {
    member1_type member1;
    member2_type member2;
    // 可以有多个成员
};

# 共用体的使用

共用体的成员可以像结构体的成员一样被访问。但是,共用体的每次赋值都会覆盖之前的值,并且只能同时使用一个成员。

union Data {
    int i;
    float f;
    char str[20];
} data;
data.i = 10;
printf("data.i = %d\n", data.i);  // 输出 10
data.f = 3.14;
printf("data.f = %.2f\n", data.f);  // 输出 3.14
strcpy(data.str, "Hello");
printf("data.str = %s\n", data.str);  // 输出 Hello

在上面的示例中,共用体 Data 有三个成员: ifstr ,它们分别是整型、浮点型和字符数组类型。因为共用体的所有成员共享同一块内存空间,所以对一个成员的赋值会影响其他成员的值。

# 应用场景

  • 节省内存:当某些数据共享同一块内存空间时,可以使用共用体来节省内存。
  • 数据类型转换:在一些特定情况下,共用体可以用于进行不同类型之间的转换。

# 11. 宏定义

# 创建符号常量

宏定义可以用来创建符号常量,这些常量在程序中可以被多次引用,提高了代码的可读性和维护性。

#define PI 3.14159
#define MAX_SIZE 100

在上面的示例中, PIMAX_SIZE 都被定义为符号常量,它们在程序中可以被多次使用而不用重复书写其值。

# 创建代码片段

宏定义还可以用来创建代码片段,这些片段在程序中被多次调用。

#define SQUARE(x) ((x) * (x))

上面的宏定义创建了一个求平方的宏,可以通过传入参数 x 来实现平方操作。

# 示例

下面是一个使用宏定义的示例,演示了创建符号常量和代码片段的用法:

#include <stdio.h>
#define PI 3.14159
#define MAX(a, b) ((a) > (b) ? (a) : (b))
int main() {
    printf("PI = %.2f\n", PI);
    
    int x = 5, y = 10;
    int max_value = MAX(x, y);
    printf("Max value = %d\n", max_value);
    
    return 0;
}

在这个示例中, PI 被定义为符号常量, MAX 被定义为求最大值的宏。

# 12. 枚举

枚举是一种用户定义的数据类型,它允许为一组相关的常量赋予符号名称。这使得代码更易于阅读和维护。

enum Weekday {
    Monday,
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
    Saturday,
    Sunday
};

在上面的示例中,我们定义了一个枚举类型 Weekday ,其中包含了一周中的每一天。默认情况下,枚举常量的值从 0 开始,依次递增。

# 13. 递归

递归是指函数调用自身的编程技术。它在解决问题时通常将问题分解为更小的、类似的子问题,直到达到基本情况。

#include <stdio.h>
int factorial(int n) {
    if (n <= 1) {
        return 1;
    } else {
        return n * factorial(n - 1);
    }
}
int main() {
    int result = factorial(5);
    printf("Factorial of 5 is %d\n", result);
    
    return 0;
}

在这个例子中, factorial 函数通过递归调用自身来计算给定数字的阶乘。

# 14. 内联函数

在 c/c++ 中,为了解决一些频繁调用的小函数大量消耗栈空间(栈内存)的问题,特别的引入了 inline 修饰符,表示为内联函数。

栈空间就是指放置程序的局部数据(也就是函数内数据)的内存空间。

inline 仅是一个对编译器的建议

#include <stdio.h>
 
inline const char *num_check(int v)
{
    return (v % 2 > 0) ? "奇" : "偶";
}
 
int main(void)
{
    int i;
    for (i = 0; i < 100; i++)
        printf("%02d   %s\n", i, num_check(i));
    return 0;
}
/*
上面的例子就是标准的内联函数的用法,使用 inline 修饰带来的好处我们表面看不出来,其实,在内部的工作就是在每个 for 循环的内部任何调用 dbtest (i) 的地方都换成了 (i%2>0)?"奇":"偶",这样就避免了频繁调用函数对栈内存重复开辟所带来的消耗。
*/

内联是以 ** 代码膨胀(复制)** 为代价,仅仅省去了函数调用的开销,从而提高函数的执行效率。

如果执行函数体内代码的时间,相比于函数调用的开销较大,那么效率的收获会很少。另一方面,每一处内联函数的调用都要复制代码,将使程序的总代码量增大,消耗更多的内存空间。

# C 语言关键字

C 语言中的关键字可以根据其功能和用途进行分类。以下是对 C 语言关键字的分类:

# 1. 数据类型声明

  • char:用于声明字符型变量或函数的返回类型。
  • int:用于声明整型变量或函数的返回类型。
  • float:用于声明单精度浮点型变量或函数的返回类型。
  • double:用于声明双精度浮点型变量或函数的返回类型。
  • void:用于指定函数无返回值或无参数,或者声明指向未知类型的指针。
  • long:用于声明长整型变量或函数的返回类型。
  • short:用于声明短整型变量或函数的返回类型。
  • signed:用于声明有符号整型变量。
  • unsigned:用于声明无符号整型变量。

# 2. 变量声明和存储类别

  • auto:用于声明自动变量,其生命周期随着代码块的结束而结束。
  • static:用于声明静态变量,其生命周期在整个程序执行期间保持不变。
  • extern:用于声明变量或函数是在其他文件中定义的。
  • register:用于声明寄存器变量,提示编译器将变量存储在 CPU 寄存器中。
  • const:用于声明只读变量,其值在初始化后不能修改。
  • volatile:用于告诉编译器变量的值可能会在外部被改变,从而防止编译器对该变量进行优化。

# 3. 流程控制

  • if:用于创建条件语句。
  • else:用于在 if 语句中指定条件为假时要执行的代码块。
  • switch:用于创建 switch 语句。
  • case:用于在 switch 语句中指定不同的情况。
  • default:在 switch 语句中用于指定默认情况。
  • while:用于创建 while 循环。
  • do:用于创建 do-while 循环。
  • for:用于创建 for 循环。
  • break:用于跳出循环或 switch 语句。
  • continue:用于跳过循环中的当前迭代,继续下一次迭代。
  • goto:用于无条件地转移到程序中的标记位置。
  • return:用于从函数中返回值。

# 4. 函数和返回值

  • void:用于指定函数无返回值或无参数,或者声明指向未知类型的指针。
  • return:用于从函数中返回值。

# 5. 结构和组织代码

  • struct:用于定义结构体类型。
  • union:用于定义共用体类型。
  • typedef:用于定义新的数据类型名称。
  • enum:用于定义枚举类型。

# 6. 内存大小和类型检查

  • sizeof:用于获取数据类型或变量的大小(字节数)。

# 7. 标记和标签

  • goto:用于无条件地转移到程序中的标记位置。
  • label_name::标签名称,通常与 goto 语句配合使用。

# 8. 条件编译

  • #if:条件预处理指令,根据条件编译指定的代码。
  • #ifdef:条件预处理指令,如果定义了指定的宏则编译后面的代码。
  • #ifndef:条件预处理指令,如果未定义指定的宏则编译后面的代码。
  • #elif:条件预处理指令,用于多个条件之间的选择。
  • #else:条件预处理指令,用于条件不成立时执行的代码。
  • #endif:条件预处理指令,结束条件编译块。
  • #define:用于定义宏。
  • #undef:用于取消已定义的宏。
  • #include:用于包含其他文件的内容。

这些关键字和预处理指令在 C 语言中起着不同的作用,能够帮助程序员控制程序的流程、声明变量和类型、组织代码结构等。理解和熟悉这些关键字的用法是编写高效、可读性强的 C 代码的重要基础。

# C 语言运算符

C 语言中的运算符是用来执行各种数学和逻辑运算的特殊符号。它们可以用于操作各种类型的数据,包括整数、浮点数、字符等。以下是 C 语言中常用的运算符及其优先级:

# 1. 算术运算符

  • +:加法运算
  • -:减法运算
  • *****:乘法运算
  • /:除法运算
  • %:取模运算(求余数)

# 2. 关系运算符

  • ==:等于
  • !=:不等于
  • >:大于
  • <:小于
  • >=:大于等于
  • <=:小于等于

# 3. 逻辑运算符

  • &&:逻辑与
  • ||:逻辑或
  • !:逻辑非

# 4. 位运算符

  • &:按位与
  • |:按位或
  • ^:按位异或
  • ~:按位取反
  • <<:左移位
  • >>:右移位

# 5. 赋值运算符

  • =:赋值运算符
  • +=:加法赋值
  • -=:减法赋值
  • *=:乘法赋值
  • /=:除法赋值
  • %=:取模赋值
  • &=:按位与赋值
  • |=:按位或赋值
  • ^=:按位异或赋值
  • <<=:左移位赋值
  • >>=:右移位赋值

# 6. 其他运算符

  • sizeof():返回数据类型或变量的大小(字节数)
  • ?::条件运算符(三目运算符)
  • ,:逗号运算符(用于分隔多个表达式,返回最后一个表达式的值)

# 7. 优先级

运算符的优先级确定了它们在表达式中的执行顺序。以下是常见运算符的优先级,按照从高到低的顺序排列:

  1. ():圆括号(最高优先级)
  2. [], ->, .:数组访问、结构体和共用体成员访问
  3. ++, --:自增和自减
  4. +, -:正负号
  5. !, ~:逻辑非和按位取反
  6. sizeof:大小运算符
  7. *, /, %:乘法、除法和取模
  8. +, -:加法和减法
  9. <<, >>:左移位和右移位
  10. <, <=, >, >=:关系运算符
  11. ==, !=:等于和不等于
  12. &:按位与
  13. ^:按位异或
  14. |:按位或
  15. &&:逻辑与
  16. ||:逻辑或
  17. ?::条件运算符
  18. =, +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=:赋值运算符(最低优先级)

了解运算符的优先级和结合性是编写正确和高效的表达式的关键。0

更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

flechazo 微信支付

微信支付

flechazo 支付宝

支付宝

flechazo 贝宝

贝宝