很多刚刚开始接触计算机的朋友都听说过C语言,但是盲目的去学习又摸不到头脑,那么这次小杨就来仔细的给大家说说C语言基础,我是嵌入式在学,也算是对自己C语言基础的一个总结,希望能够给各位一点帮助。

C语言简介

首先C语言是一种高级计算机语言,相比于其他的高级语言而言,C语言更贴近硬件,能够直接操作内存,硬件设备,其运行的效率也是最高的,运行所需的硬件开销也是最小的。

C语言的组成

    一、关键字:  这是由编译器定义的,有特殊含义的词汇,不能用作其他用途。

 类型相关的:  
     auto、char、const 、double、extern 、float、int 、longregister 、short  、signed 、unsighed    void 、static、enum 、union 、struct

其中常见的是我们平时定义变量或者常量的类型关键字。
    
    结构相关: 
    if else、goto、 for 、do、while  、break 、continue 、 switch 、 case 、default 、return               sizeof 、typedef 、volatile 

这些是在C语言中,常见的结构相关的关键字,比如循环结构输入输出等。

二、标识符:这一类是由编程者自定义的名字,一般是变量名、函数名等。只能由数字、字母 、下划线 组成  ,不能以数字开头 ,不能与关键字重名。

例如定义一个函数   void  AAA();其中AAA是可以由编程中自定义的。

三、运算符:由编译器定义的特殊标点符号,表示数学运算或某些特殊动作。

按功能可以分为:    
    算术运算符:   + - * /   %  取余数                    结果为 一个数值 
    逻辑运算符:  逻辑与  &&     逻辑或||   逻辑非!    结果为真(1 非0 )或假 ( 0 )
    关系运算符:   比大小  > <  >= <=  ==  !=          结果为真(1 非0 )或假 ( 0 )
    位运算符:    将数值以二进制方式进行运算  

     按位与 &   按位或 |  按位亦或 ^     按位取反~    按位左移<<    按位右移 >> 
    赋值运算符:  更新变量的值  a  =+ B  ===>  a = a + b
        =   +=  -=  *=  /=
    递增递减运算符:  ++  --    单目运算符  a++; ++a;
    地址运算符:  取地址运算 &a      取值运算符 *地址  
    逗号运算符:  ,       1,a+=2,3   使用','分割各个表达式,其值为最后一个表达式的值 但 其他表达式都会执行一次 
    sizeof运算符  sizeof() 计算变量占用的存储空间 
    三目运算符:   表达式1  ?  表达式2 : 表达式3 

    单目运算符:运算符与 一个值或变量 进行运算 
    双目运算符:运算符与 两个值或变量 进行运算  通常运算符在中间(中值表达式)
    三目运算符:运算符与 三个值或变量 进行运算
    表达式:  由 变量或值 与  运算符 有序结合构成的 句子
    表达式的值:  将表达式 进行 计算 计算的结果 为 表达式的值

这部分可以看看我的另一篇文章,其中有详细的讲解:C语言基础中,各种符号的优先级以及应用_久歌啊的博客-CSDN博客

四、分隔符:一般为了程序的美观、易读而引入的一些排版操作,不影响程序本身。

例如:空格、回车换行、制表符、注释

其中单行注释是//,多行注释可以使用/*        */进行,也可以使用#if0             #endif进行注释。

五、标点符号:程序中标点符号会参与程序的表示,需要严格按照规定使用。有些标点符号出现在表达式中作为运算符使用。 

    每一条C代码的 结尾 需要使用; 作为结束符 。

所有符号 均严格区分大小写, 严格区分中英文 。

'#'开头的标志符 用于给编译器使用  指定如何编译这个C代码 

C语言的数据类型

类型:表示数值的存储以及表示方式。

基本数据类型

一、布尔类型:其输出的值为真或者假 ,数值bool判读,非0为真 0为假。

       精确类型:

                 1.整型:(4字节宽度)使用int ,一般表示一个数值其取值范围为-2^31~+2^31-1

                在计算机中 有符号数的表示:使用最高位表示符号位 0为正1为负数。负数 采用 补码方式表示  方便进行无差别算数运算。

补码 转换为 负数 :  补码 取反 + 1。

                2.短整型(2字节存储):short(signed short )

                3.字符型(一字节存储):char 、signed char  unsigned char 0-255,也可以存储一个字符的ASCLL码。

                4.长整型:long int。

                5.浮点型(四字节存储):float 表示小数,属于小数的非精确表示。

                                                          其中又有八字节浮点数:double

                6.void型:表示空类型,只用于 :
                        1.描述 函数的返回值或 参数没有。 
                        2.指针 指向的类型 不确定 或 任意类型。

二、常量:在设计程序时就确定的,不会在程序运行过程中改变的量。

                1.数值常量:表示常用的数值。10、5、6。

                2.指数常量:既将常量定义为指数形式。例如3.5789e-8  表示 3.5789 * 10 ^-8 

                3.字符常量:char型,'A','B',其本质是对应字符的编码值,即ASCLL码。

                4.字符串常量:使用双引号"A","abc","sadada",由多个字符,连续存放在内存中。而且有一个结束符'\0',即值为0;

                  标志常量可以使用宏定义:类似于字符串替换。

                                #define  PI  3.14
                                 #define  G   9.8

三、变量

变量是可以根据程序的运行改变的量,其本质是一个容器,可以存放数的容器。

在C语言中定义一个变量其本质是向CPU申请一个存储空间。

        1)变量定义格式

                        存储类型     数据类型   变量名;

                   一般存储类型省略如:int x;float a;

        2)数据的存储类型:

                1. auto:  自动类型,可以省略,由编译器决定存储位置。 
                2. static: 静态区 ,修饰变量时表示指定该变量空间在静态区。
                3.register: 寄存器存储类型 表示该变量应放到CPU的寄存器中不是强制的只是建议 。
                4.extern : 引用存储类型多文件编程中表示不需要给该变量分配存储空间,表示在其他文件中已经被定义了该文件只是引用该变量。 
                5.const:  常量类型,指定变量的存储空间位于常量区仅在修饰全局变量时若 const 修饰局部变量其存储空间位置不会改变,仅表示该变量只读 。

          3)C语言内存存储位置

                    1. 代码段/常量区:该段内存只读不允许修改。 
                    2. 静态区:该段内存 可读可写  在程序运行前就分配好了,且其中的 变量会 一直存在直到程序结束 (生命周期长),包括:

                        全局变量(在函数外定义的auto变量) 或 静态变量(使用static 修饰的变量) 。
                    3. 栈区:该段内存 会自动(在程序运行中)分配 。包含:
                                局部变量      临时变量      函数的形参       函数调用
                    4. 堆区:该段内存 由程序运行时 程序员设计 申请与释放(分配)。

           4)变量类型的转换

当不同类型数据间进行运算或者赋值等操作时,存在类型的转换。

                     1.隐式类型转换:

                        转换规则:将精度低的向精度高的转换。

                                          将范围小的往范围大的转换。

                                          有符号数 往 无符号转换 。

                     2. 强制类型转换:

                        手动的将一个类型转换为另一个类型 。当转换的精度不匹配时, 会存在数据精度丢失的问题,显式的数据类型转换实现的一般形式为:        
                                (目标数据类型名称)< 表达式 >    (int)(A+B)  表示将A+B的结果强制转换为整型。

四、运算符与表达式

                 基础中运算符与表达式按功能可以分为:算术运算符、逻辑运算符、算术运算符、逻辑运算符、关系运算符、位运算符、  赋值运算符、递增递减运算符、地址运算符、逗号运算符、sizeof运算符 、 三目运算符。 具体所包含的运算符如下:

 运算符的具体讲解可以看小编的另一篇文章:C语言基础中,各种符号的优先级以及应用_久歌啊的博客-CSDN博客

C语言的输入输出

C语言输入输出包括字符界面和终端。

一、字符输出: 

putchar();   //输出一个字符到终端 
putc(); //输出一个字符到终端
puts();  //输出字符串 
fputs(); // 字符串的格式化输出 
printf(); printf( 格式控制字符串, 可变长参数表 );

格式控制字符串: 是一个使用"" 引起来的 一个字符串常量,包含

      占位控制符  以 '%' 开头的一段字符

            %d  %i  十进制数 
            %x  %X  十六进制数 
            %u      无符号十进制数
            %c      一个字符 
            %s      一个字符串 
            %e      指数形式显示 
            %f      小数形式显示 
            %%      输出字符'%' 本身

    附加格式说明符(修饰符):

 位置放在 % 与 占位控制符 之间指定输出字符宽度     %4d 
    输出宽度对齐  默认 右对齐   %-8d  左对齐 
    输出小数,指定小数位数  %.2f  保留2位小数 四舍五入
    %#x  输出十六进制数 附带前缀 0x


二、C语言的终端输入: 


    getchar(); 从终端读取一个输入字符
    fgets(); 从终端输入一个字符串 
    gets();  有溢出风险 已经弃用
    cat 文件名:将文件中的内容 显示到终端上

执行到输入语句时,程序会 阻塞等待 用户输入

Ubuntu man手册 可以用于查看 函数 查看命令 

   带格式的输入  scanf();
    输入整数  "%d"  
    输入小数  "%f" 

%*  取出然后丢弃

scanf("%[^\n]s",s);  // 取出除'\n'以外的其他字符, 直到'\n'退出

scanf("%[0-9]",s); // 值取出数字 直到不是数字的字符 退出 

当多个输入在scanf中时, 若有分割格式, 就严格按照格式 提取
    若没有分割格式, 默认以 空格 制表符 回车 作为分割 。

可以指定宽度取值:示例:20221221    提取指定宽度数据  scanf("%4d%2d%2d", &y,&m,&d);

指定取出字符:

scanf注意事项
        scanf输入会有 数据残留在输入中   
        如何判断 输入是成功的 还是失败的? 
        通过scanf函数返回值 <= 0 输入失败  >0 表示输入成功的个数

 C语言的多分支结构

多选多的模式     switch case:

结构:

Switch (常量表达式)

{

Case 常量1:语句块1

Case 常量2:语句块2

Case 常量3:语句块3

.。。。。。。。。。。。。。

Default: 语句块n;

}

整型常量表达式:其运算结果是一个整型常量

运行逻辑:

计算    整型常量表达式的值,对该值匹配“==”case中的常量

若匹配,则执行相应的语句块。

示例如下所示:

循环结构

While循环:

结构1:

do{ 循环语句块}  while(条件表达式);

运行逻辑:先无条件执行一次,再判断,真-执行,假-结束

结构2:

While(条件表达式){}、

运行逻辑 :先判断再执行。

            实际 常用的是结构体2;

For循环

结构:

for(表达式1;表达式2;表达式3)

{

循环体;;

}

运行逻辑:1执行一次 表达式1,完成初始化

2判断表达式2 真还是假

若真 执行循环体

3执行表达式3

4 回到动作2继续执行

若假:退出for循环。

 

循环的3部分:

  1. 循环的准备动作,初始化,通常只执行一次
  2. 循环体,语句块;多次执行
  3. 向退出条件靠近的语句

 goto

goto实际是程序的跳转

结构:

1)在需要跳转的地方加上标识格式的标识名。

2)在需要跳转的位置运行 goto  标识名。

goto的注意事项:

 

 数组

数组: 是一种构造的数据类型 
    将多个相同类型的数据在内存中有序 连续存放 这种结构称作 数组结构 
    元素:  数组中的单个数据称作数组的元素
    数组的定义:  
                      存储类型   数据类型  数组名 [ 元素个数 ];
    存储类型:  决定数组在内存中的区域
    数据类型:  决定数组元素的类型 
    数组名:    一个标志符 自定义 
    []  :      是标点符号 不能缺少  表示这是一个数组 
    元素个数:  指定数组元素的个数  目的是指定占用的内存
                            元素个数计算== sizeof(数组名) / sizeof( 元素类型 )
    数组名:          (1) 代表这个数组   arr[0]
                          (2) 代表这个数组的首地址   arr
    首地址: 变量在内存中所占用的内存的开始地址地址小的那端   
数组的初始化: 
    int arr[3+2] = {1,2,3,4,5};
    int arr[5] ={1};  
     若初始化中的元素个数 少于指定的个数, 其他没有初始值的元素将会指定初始为0
    此种情况 元素个数必须定义时指定。

在数字初始化中 可以省略指定个数, 编译器会根据初始化表中的元素个数 指定大小。
    int arr[] = {1,2,3,4,5};

数组元素的引用: 
    格式:   数组名[元素下标]

元素下标: 对数组的每个元素进行编号, 从左到右从0开始编号。可以是正整数常量表达式, 也可以正整数变量表达式。

                 arr[4]  // 代表arr数组中的 编号为4 的 元素 。这是一个表达式  其表达式的值 即 arr数组中的 编号为4 的 元素 。

数组的越界操作: 
        是非法的内存访问, 其结果不可预知
        1. 段错误  被系统杀死 
        2. 数据不保证可靠

通常数组的元素连续访问  使用循环 

    数组的遍历:  循环
    两个类型相同的数组 相互赋值?
    int arr1[5] = {1,2,3,4,5};  int arr2[5];
    arr2[i] = arr1[i];

数组的遍历循环和遍历比较:

 字符数组 与字符串:
字符串: 一定有结束符"\0" , 可能是常量 "hello"
在数组中 连续存放了 一些字符, 可能没有'\0'  通常是变量 ;

二维数组与多维数组: 
    将 多个相同类型的数据在内存中有序连续存放这种结构称作 数组结构 。
    元素:  数组中的单个数据称作数组的元素。
    二维数组: 即 数组的元素 是一个数组, 称作二维数组,  
    数组元素不是数组的 称作一维数组, 
    多维数组:  数组的多层嵌套 
    int arr[5] ; // 类型 int [5];
    int arr1[6];// 类型 int [6];

变量的类型: 
    int a;  // 类型 int
    int x[3]; // 类型 int [3];
二维数组的定义: 
    存储类型  一维元素的元素的数据类型  二维数组名[一维元素个数][ 一维元素的元素个数 ];
               int                          xy[2][3];    

示例:  float a[3][2]; 问该定义是什么含义?
    定义了一个 二维数组; 数组名为 a ; a中的一维元素是  一个一维数组 ,a中 有 3个 一维数组;
    这个一维数组  有 2个 元素 , 其元素类型为 float 型 ,共有 6个  float类型数据 ;

二位数组的访问

示例:

         float a[3][2];
若访问 a中的 第0个元素   表达式是 a[0];  
   a[0]的类型: 一维数组类型, 有2个float类型的元素,   float [2];
若访问 a[0] 的 第1个元素 表达式是 a[0][1]; 
     a[0][1] 即表示访问float a[3][2]中的第0位一维元素中的编号为1的元素。
     

三维以及多维: int arr[2][3][4];  
    arr          类型  int [2][3][4];
    arr[0]       类型  int [3][4];
    arr[0][1];   类型  int [4];
    arr[0][1][1];类型  int ;

多维数组初始化: 
    int a[5] = {1,2,3,4,5};

    int cjb[2][5] = { {1,2,3,4,5}  , {6,7,8,9,10} };

以此类推:也可全为0;

 int cjb[2][5] = {0};

函数: 

什么是函数?
    将某些完成特定功能的 代码的 有序集合;
    
函数的定义: 
    返回值类型   函数名 (形参列表)
    {
        函数体;; // 代码块
        return ;
    }

返回值: 一个函数即一个特定的功能 对于该功能 可能需要输出或返回执行的结果给调用者
返回值类型: 即指定 函数返回值的类型;
函数名: 标志符 自定义  不能与同文件的其他函数重名 

形参列表: 代码块完成该功能 可能需要外部给定一些参数  

函数调用:  执行代码块 
    函数名(实参列表);

形参与实参: 
    实参是调用者 传递给函数 的 形参的值 , 是实参值的拷贝;
    函数操作形参 是不会影响实参的。
地址传参: 即 形参传递的内容是 实参的地址, 此种情况下 可以通过这个地址(形参) 操作实参 。

函数声明: 
    在函数被调用前, 将除函数体外 的部分 放在调用前的 函数外; 

函数原型: 除函数体,剩下的部分即函数原型

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐