纯小白自学C基础的总结(望指正)!

本文介绍了C语言的基础知识,包括在Ubuntu上编译程序的步骤,C程序的组成,如预处理指令、函数定义、数据类型、运算符和表达式。还涵盖了输入/输出、分支和循环结构,以及数组的使用。此外,讨论了函数参数传递、递归函数和多源代码文件的编译。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        作为一个小白,在各大视频和参考书籍(C Primer Plus等)的帮助下,马马虎虎完成了C基础的理论学习和部分项目的实现,以下是我学习的相关书籍顺序以及我认为平常学习需要注意的点,个人拙见,可能存在不足和错误,望大家慷慨指导,谢谢!

1. C语言的概述及Ubuntu上编写程序的操作

C语言的概述:

        C语言是一种通用的高级编程语言,由Dennis Ritchie在20世纪70年代早期在贝尔实验室开发。C语言以其简洁、高效和灵活的特点而受到广泛欢迎。它在系统编程、嵌入式系统和操作系统开发中得到广泛应用。

Ubuntu上编写程序的操作:

1. 安装编译器:Ubuntu默认安装了GNU C编译器(GCC)。如果没有安装,可以在终端中运行以下命令安装:`sudo apt-get install gcc`

2. 编写代码:使用文本编辑器(如`nano`、`vim`或`gedit`)编写C代码,并将其保存为.c文件。

3. 编译代码:在终端中,使用GCC编译器将C代码编译成可执行文件。命令格式:`gcc a.c`

4. 运行程序:在终端中,通过输入可执行文件名来运行程序。例如:`./a.out`

2. C语言程序的组成

1.预处理指令:

        预处理指令以`#`符号开头,告诉编译器在实际编译之前对代码进行预处理。例如,`#include`用于包含头文件,`#define`用于定义常量。

2.函数定义:

        C程序由一个或多个函数组成。每个C程序至少有一个主函数(`main`函数),它是程序执行的起点。

3.全局变量声明:

        全局变量在函数外部定义,可以在整个程序中使用。它们在函数调用之间保持值的持久性。

4.主函数:

        主函数(`main`函数)是C程序的起点,程序从这里开始执行。它必须存在,并且只能有一个。

3. C语言的基本构成元素和数据类型

1.标识符:

        在C语言中,标识符是用来标识变量、函数、结构等的名称。标识符由字母、数字和下划线组成,必须以字母或下划线开头。

2.关键字(32个):

        关键字是C语言中预定义的具有特殊含义的单词,例如`int`、`if`、`else`等。它们不能用作标识符。

参考百度百科:

        

auto :声明自动变量

break:跳出当前循环

case:开关语句分支

char :声明字符型变量或函数返回值类型

const :声明只读变量

continue:结束当前循环,开始下一轮循环

default:开关语句中的“默认”分支

do :循环语句循环体

double :声明双精度浮点型变量或函数返回值类型

else :条件语句否定分支(与 if 连用)

enum :声明枚举类型

extern:声明变量或函数是在其它文件或本文件的其他位置定义

float:声明浮点型变量或函数返回值类型

for:一种循环语句

goto:无条件跳转语句

if:条件语句

int: 声明整型变量或函数

long :声明长整型变量或函数返回值类型

register:声明寄存器变量

return :子程序返回语句(可以带参数,也可不带参数)

short :声明短整型变量或函数

signed:声明有符号类型变量或函数

sizeof:计算数据类型或变量长度(即所占字节数)

static :声明静态变量

struct:声明结构体类型

switch :用于开关语句

typedef:用以给数据类型取别名

unsigned:声明无符号类型变量或函数

union:声明共用体类型

void :声明函数无返回值或无参数,声明无类型指针

volatile说明变量在程序执行中可被隐含地改变

while :循环语句的循环条件

3.常量:

        常量是在程序中固定不变的值,可以是整数常量、浮点数常量、字符常量或字符串常量。

4.变量:

        变量是用于存储数据的内存位置。在使用变量之前,必须先声明其数据类型。

     变量分为:整型变量([ ]int),实型变量(float, double, long double),字符型变量(char)。

5.数据类型:

        C语言提供了基本数据类型,如整型(`int`)、字符型(`char`)、浮点型(`float`)等。还有派生数据类型,如数组、结构体和指针。

注意:

        1.理解标识符的命名规则和约定,避免命名冲突和错误。标识符由字母、数字和下划线组成,必须以字母或下划线开头。

        2.理解不同数据类型的用途和表示范围,特别是在进行数据类型转换时要注意数据溢出和精度丢失。

        3.auto、static、register、extern变量的作用及具体用法。

      4.隐式类型转换和强制类型转换的使用,C语言强转中要把类型说明符给括起来,k=(int)(a+b); 

4. 运算符和表达式

1.算术运算符:

        C语言提供了基本的算术运算符,如`+`、`-`、`*`、`/`和`%`。它们用于执行基本的算术计算。

2.逻辑运算符:

        逻辑运算符用于执行逻辑操作,如与(`&&`)、或(`||`)和非(`!`)。

3.关系运算符:

        关系运算符用于比较两个值,如等于(`==`)、不等于(`!=`)、大于(`>`)、小于(`<`)、大于等于(`>=`)和小于等于(`<=`)。

4.赋值运算符:

        赋值运算符(`=`)用于将值赋给变量。a=10;即将10赋值给变量a。

5.位运算  计算机中特有的运算   所有运算目标 均针对二进制而言

              按位             &    将二进制中的每一位进行与操作   与0得0  与1不变

              按位             |    将二进制中的每一位进行或操作   或1得1  或0不变

              按位取反       ~    单目运算

              按位异或       ^    相同为0  不同为1

       移位运算:

              逻辑左移    <<    高位移出丢弃 低位补0

              算数右移    >>    低位移出对齐 无符号数 高位补0  有符号数 高位补符号位。

6. 表达式:

        表达式由运算符和操作数组成,用于执行计算并生成结果。表达式的结果可以是常量、变量或复杂的算术值。

注意:

        1.熟悉各种运算符的优先级和结合性,避免表达式计算出现错误。在表达式中使用括号来明确优先级。如:a=2, 5-1, 4+3, 6*9;  此时a的值为2,不是54,因为赋值运算符的优先级高于逗号运算符,可以加()以提升逗号运算符的优先级。

        2.注意逻辑运算符的短路特性,以避免不必要的计算:

        (表达式1)&&(表达式2):

        如果表达式1为假,则表达式2不会进行运算,因为此时不管表达式2值为什么,输出都为0,编译器直接跳过表达式2,即表达式2“被短路”。

        (表达式1)||(表达式2):

        如果表达式1为真,则表达式2不会进行运算,即表达式2“被短路”。

        若表达式2存在’=’赋值运算,如a=3,此时3因为短路特性将不会被赋值到a中,若此时求a的值,输出不为3,特别注意。

5. 用户与计算机交互——输入/输出

1.输出函数(`printf`):

        `printf`函数用于将数据输出到屏幕上。它可以输出字符串、变量的值以及其他格式化的输出。

2.输入函数(`scanf`):

        `scanf`函数用于从用户获取输入数据。它根据格式字符串读取用户输入,并将输入的值存储在变量中。

注意:

        1.在使用printf函数时,注意控制输出格式,以确保输出内容的正确性和可读性。使用格式化字符串,如%d、%f、%c和%s来输出不同类型的数据。

        2.使用scanf函数时,注意对输入的验证和错误处理,以避免程序崩溃或陷入死循环。在输入数据时,确保输入的数据类型和格式与scanf函数中的格式字符串相匹配。

6. 分支结构程序设计

1.`if`语句:

        `if`语句用于根据条件执行不同的代码块。如果条件为真,执行`if`语句后的代码块;否则,跳过`if`语句,执行其他代码。

2.`else`语句:

        `else`语句用于在条件为假时执行另一个代码块。

3.`switch`语句:

        `switch`语句根据表达式的值,选择执行不同的代码块。它可以替代多个`if-else`语句。

注意:

        1.对于多个条件的判断,理解if-else和switch语句的选择使用,以及注意避免嵌套过多的if-else语句。

        2.在使用switch语句时,注意每个case后面需要添加break语句,以防止出现不必要的执行。但针对特定情形可以利用switch…case…不加break完成程序的连续累加。例如,求某个日期是当年的第几天,可以通过这一特性将每月的天数累加到一个变量中。

7. 循环结构与转移语句

1. `for`循环:

        `for`循环用于重复执行一段代码,它有初始化、条件和更新三个部分,可以在循环执行之前和之后执行一些操作。

2. `while`循环:

        `while`循环在循环执行之前检查条件是否为真,如果为真,则执行循环内的代码。

3. `do-while`循环:

        `do-while`循环先执行一次循环内的代码,然后在循环条件为真时重复执行。

4. 转移语句:

        `break`语句用于在循环中提前跳出循环。`continue`语句用于结束当前循环迭代,进入下一次循环迭代。

5.嵌套循环:

        指在一个循环中包含另一个循环。常用于按行和列显示数据,就是外循环处理行,内循环处理列。

#include <stdio.h>

int main() {
    int rows = 5;

    for (int i = 1; i <= rows; i++) {
        // 打印空格
        for (int j = 1; j <= rows - i; j++) {
            printf(" ");
        }

        // 打印星号
        for (int k = 1; k <= i; k++) {
            printf("* ");
        }

        printf("\n");
    }

    return 0;
}

输出的结果如图:

    *
   * *
  * * *
 * * * *
* * * * *

注意:

        1.理解循环结构的退出条件和循环体的执行次数,避免无限循环,如while(1),for(;;){}。

        2.注意在使用转移语句时,确保程序逻辑正确,避免使用过多的转移语句造成程序流程混乱。

8. 数组

1.一维数组:

        一维数组是由相同类型的元素组成的数据结构,通过索引可以访问数组中的元素。

2. 二维数组:

        二维数组是由多个一维数组组成的数据结构,可以使用两个索引来访问数组中的元素。

3.字符数组:

        字符数组是用于存储字符串的一种特殊的一维数组。

4.数组的排序算法:

        常见的排序算法,如冒泡排序、插入排序和快速排序等,用于对数组进行排序。

5.字符串处理函数:

        C语言提供了许多用于处理字符串的库函数,例如`strlen`、`strcpy`和`strcat`等。

6.数组的遍历:

        数组是C语言中的一种数据结构,用于存储一系列相同数据类型的元素。数组提供了一种有效的方式来组织和访问大量相似数据,并且在程序中使用广泛。

声明和初始化数组:
        在C语言中,声明数组需要指定数组的数据类型和数组名,并使用方括号`[]`来表示数组的大小。


// 声明一个整型数组arr,包含5个元素
int arr[5];

        数组的元素可以通过索引访问,数组索引从0开始,直到数组大小减1。

        数组的初始化可以在声明时进行,也可以在后续代码中逐个赋值。以下是两种初始化数组的方式:

// 声明并初始化整型数组arr
int arr1[5] = {1, 2, 3, 4, 5};
// 声明整型数组arr,并逐个赋值
int arr2[5];
arr2[0] = 1;
arr2[1] = 2;
arr2[2] = 3;
arr2[3] = 4;
arr2[4] = 5;

        数组的大小是固定的,一旦定义后,大小不能再改变。

访问数组元素:
数组元素可以通过数组名和索引来访问。索引用于标识数组中的元素位置,可以是整型表达式或常量。

int arr[5] = {10, 20, 30, 40, 50};

// 访问数组元素
int firstElement = arr[0]; // 第一个元素,值为10
int thirdElement = arr[2]; // 第三个元素,值为30

// 修改数组元素
arr[1] = 25; // 将第二个元素的值修改为25

        需要注意的是,数组索引应该在合法范围内,否则会导致访问越界,可能引发未定义行为或程序崩溃。

 多维数组:
        C语言支持多维数组,即数组中的每个元素也是一个数组。常见的二维数组是最常用的多维数组。

// 声明一个二维整型数组matrix,包含2行3列
int matrix[2][3] = {
    {1, 2, 3},
    {4, 5, 6}
};

        多维数组的访问需要指定每个维度的索引。
 

// 访问二维数组元素
int element = matrix[1][2]; // 访问第2行第3列的元素,值为6

数组的传递和函数:
        在函数中,数组可以作为参数传递。数组作为函数参数时,传递的是数组的地址。因此,函数内部可以直接操作原始数组。

void printArray(int arr[ ], int size) {
    for (int i = 0; i < size; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
}

int main() {
    int arr[ ] = {1, 2, 3, 4, 5};
    int size = sizeof(arr) / sizeof(arr[0]);
    printArray(arr, size); // 数组作为参数传递给函数
    return 0;
}


 

总结:
        数组是C语言中用于存储一系列相同数据类型元素的数据结构。通过索引,可以访问数组中的每个元素。数组的大小在声明时确定,一旦定义后,大小不能再改变。C语言支持多维数组,使得数组可以用于更复杂的数据组织。在函数中,数组作为参数传递时,传递的是数组的地址,函数内部可以直接操作原始数组。使用数组可以提高程序的效率和可读性,是C语言中常用的数据结构。

注意:

        1.理解数组的内存布局和索引,特别注意数组越界访问的问题。数组越界可能导致程序崩溃或产生未定义行为。

        2.理解字符数组与字符串的关系,以及字符串处理函数的正确使用。字符串在C语言中以null字符\0结尾。

9. 函数

1.函数的定义和调用:

        函数的定义和调用是C语言中非常重要的概念。函数允许我们将代码划分成独立的块,并在程序中多次使用。下面我们来详细讲解函数的定义和调用:

函数的定义:

        在C语言中,函数的定义包括函数头和函数体。函数头指定了函数的返回类型、函数名和参数列表,函数体包含了函数的具体实现。

函数定义的一般形式如下:

返回类型 函数名(参数列表) {

    // 函数体

    // 在这里编写具体的代码

    return 返回值; // 返回值的类型必须与函数声明中的返回类型匹配

}

其中:

        返回类型:指定函数返回的数据类型。C语言支持多种返回类型,如整型(`int`)、浮点型(`float`)、字符型(`char`)等。

        函数名:标识函数的名称。函数名必须是一个有效的标识符,用于在程序中调用函数。

        参数列表:指定函数接受的输入参数。参数列表包含了参数的数据类型和名称,多个参数之间用逗号分隔。如果函数不需要接受参数,可以使用空的参数列表`void`表示。

以下是一个简单的函数定义的例子:

// 函数定义,该函数接受两个整型参数并返回它们的和

int add(int a, int b) {

    int sum = a + b;

    return sum; // 返回计算结果

}

函数的调用:

        函数定义只是定义了函数的结构和实现,并没有实际执行。要调用函数,需要在程序的其他地方使用函数名加上一对小括号,并在括号内传递函数所需的参数。

函数调用的一般形式如下:

返回值变量 = 函数名(参数1, 参数2, ...);

其中:

        返回值变量:用于接收函数的返回值。函数的返回值可以是任何数据类型,需要用一个对应的变量来接收。

        函数名:指定要调用的函数的名称。

        参数1, 参数2, ...:是传递给函数的实际参数。这些参数的数据类型和顺序必须与函数定义中的参数列表匹配。

        以下是使用上面定义的`add`函数进行调用的例子:

int result = add(5, 3); // 调用add函数,传递参数5和3,并将返回值保存到result变量中

        在调用函数时,程序会跳转到函数的定义位置,执行函数体中的代码,然后将结果返回到调用处。函数调用使得程序结构更加清晰,能够重复使用特定功能的代码块。

        总结:函数的定义和调用是C语言中重要的概念。定义函数时需要指定返回类型、函数名和参数列表,并在函数体内实现具体的功能。调用函数时,需要使用函数名并传递相应的参数,以获取函数的返回值或执行特定的功能。函数的使用使得程序模块化,提高了代码的可读性和重用性。

2.函数参数传递:

        函数参数传递的不同方式,包括值传递(单向的,实参到形参)、指针传递(双向,但是回来的路与去的路不一样,相当于进入另一个车道回来,而不是原车道。)和引用传递。

        在C语言中,没有显式的引用类型但可以通过指针来模拟引用传递。引用传递与指针传递类似,但更直观,更容易理解。

// 引用传递示例(使用指针模拟引用传递)

void swap(int &x, int &y) {

    int temp = x;

    x = y;

    y = temp;

}



int main() {

    int a = 5, b = 10;

    swap(a, b); // 通过传递a和b的引用(指针)来进行参数传递

    printf("a = %d, b = %d\n", a, b); // 输出结果为 "a = 10, b = 5"

    return 0;

}

        注意:C语言中没有直接的引用类型,引用传递是通过传递指针来实现的。在C++中有引用类型,可以更直接地实现引用传递。

3.递归函数:

了解递归函数的概念和用法,以及递归函数的优缺点和适用条件。

4.编译多源代码文件的程序:

        在Linux系统中安装GNU C编译器GCC。编译两个内含C函数的文件,用gcc a.c b.c生成名为a.out的可执行文件,这是C语言模块化的直接体现,C语言模块化离不开函数。

注意:

        1.理解函数的返回值和参数传递,注意函数调用时参数的匹配。

        2.在使用递归函数时,注意控制递归深度和递归结束条件,以防止栈溢出和无限递归。

        3.C语言模块化是为了方便一个项目进行分工协作,最后再由“总工”合并,完成一个项目。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

在知识的海洋里划船

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值