小白快速学C语言

小白快速学C语言


C 语言是一种通用的、面向过程式的计算机程序设计语言。由于C语言是一个较为底层的编程语言,通过学习C语言,能够快速的从操作系统层面到编程语言层面有个宏观的理解,是各大高校与计算机相关方面研究生的必备语言之一。

本教程服务于编程小白、大一新生、研究生考试等基础人群,旨在通过最简短的例子与说明让其快速读懂、书写简单的C语言,是一个Boost学习方案。如若有充裕的时间,作者诚恳的建议从零学起,扎实基础。

本教程借鉴了菜鸟教程的相关内容,菜鸟教程致力于编程技术普及化,是一个极好的互联网技术学习网站。

目录


  • 基础语法
  • 数据类型
  • 变量与常量
  • 运算符、判断、循环
  • 函数、作用域、头文件
  • 结构体、共用体
  • 指针、数组、字符串、输入输出流、内存管理

基础语法


C语言的基础知识

  • C语言程序由函数构成,每个函数可以实现一个或多个功能。

  • 一个正规程序可以有多个函数,但是有且只有一个主函数(main)。

  • 函数只有在被调用的时候才执行,主函数由系统调用执行。

  • 函数的格式必须按照规范书写。

  • C 语言程序文件的后缀为 .c 或 .h。

我的第一个C语言程序

#include <stdio.h>

int main(int argc, char *argv[]){
    printf("Hello World!!\n");
    return 0;
}

C语言的本质是令牌语言:关键字、标识符、常量、字符串值、符号等令牌组成。

一条语句的拆解:printf ( "Hello World!!\n" ) ;

标识符(变量)命名规则

一个标识符以字母A-Za-z 或下划线 _开始,后跟零个或多个字母、下划线和数字(0-9),请注意变量名不能为保留字(关键字、基础类型等)。

int a;    int _a;    int A;    int a1; // 正确的变量命名
int 1;    int 1a;    int void; int if; // 错误的变量命名

常用的标识符命名规则如下:

  • 变量:建议全小写或驼峰命名(第一个单词首字母小写其余单词首字母大写)
  • 函数:帕斯卡(Pascal)命名法(所有首字母大写)
  • 常量:建议定义为宏(宏字母全大写)
  • 结构体等:建议全大写或帕斯卡(Pascal)命名法

标识符命名规则不唯一,请遵循开发文档,或编写自己的程序时统一标准。

C语言的注释

C语言有两种注释的方式:单行注释与多行注释。

// 单行注释
/*
多行注释
*/

C语言被注释的文字将被解释为空格存在, 而C语言会自动忽略所有空格,从而达到注释的目的。

数据类型


数据类型是语言内精髓的存在,是经过多年的版本迭代最优的考究,因此每一门语言的数据类型都值得去仔细学习,此文章只用于知识普及与快速上手编程,在此不作详细说明。

基本数据类型

int i = 0;       // 整型数据
char ch = 'a';   // 字符型数据/整型
float f = 3.14f; // 浮点型数据
double d = 3.14; // 双精度浮点型数据

浮点型数据不以fF结尾默认以双精度浮点型形式存在。

枚举类型

枚举类型用于定义一组具有离散值的常量(同数据类型)。

枚举类型常与switch语句结合使用,在后续会提及。

// 定义枚举类型
enum MyBool
{
    FALSE = 0, // 初始化第一个枚举项
    TURE       // 后续枚举项会自动初始化为上一个枚举量的自加(+1)值
};
// 定义枚举变量
enum MyBool _bool;

void类型

顾名思义,void类型即表示什么类型都不是,通常用于函数参数、指针指向类型等。无类型不代表无用,在很多场景下用处非常大。

void func(void)
{
    void *ptr = NULL; // NULL在C语言中等同于0
    return;
}

其他派生类型

C语言中还有许多派生类型:数组类型、指针类型、结构体类型。在此只说明如何定义,在后续会重点介绍用法与特性。

int a[10] = {0};        // 数组类型
int *ptr = NULL;        // 指针类型
typedef struct MyStruct // 结构体类型  
{
    int i;
} MyStruct;

无符号类型

标准整型都支持定义对应的无符号类型

unsigned int ui = 1; // 无符号指的是无符号,即不能表示负数,正数上限增大(0~255)
signed int si = 1;   // 有符号与之对应(-128~127)
unsigned char uch = 'a';

思考一个问题:C语言有符号int整型变量中 0 是怎么存储的,有 -0 吗?

类型转换

// 隐式类型转换:自动转换(小数据到大数据)
int i = 10;       // 4字节大小
float f = 3.14;   // 4字节大小
double d = i + f; // d是8字节大小,隐式转换i

// 显式类型转换:手动强制转换(大数据到小数据),容易产生数据丢失或截断
d = 3.14159; // d是8字节大小
i = (int)d;  // i是4字节大小,显式转换d

类型转换中涵盖了很多知识,包括底层内存是怎么操作的?什么是强制类型转换?一定会转换成功吗?转换失败了怎么办?不同数据类型的可以转换吗?等等问题。当然在此作者不过多阐述,想要了解的同学经过系统性的学习一定要清楚上述问题的答案。

变量与常量


对于C语言初学者来说,变量真是一个晦涩难懂的概念。变量其实只不过是程序可操作的存储区的名称,C语言中每个变量都有特定的类型,类型决定了变量存储的大小和布局,该范围内的值都可以存储在内存中,运算符可应用于变量上。

举个例子。现在需要定义一个int类型(4字节)的变量 i ,则需要在内存中开辟四字节大小的空间,如果初始化 i1 ,则需要把 1 存入这4字节的内存空间中,当然是以二进制形式存入。这两就完成了一个int类型变量的定义及初始化,而 i 即为这个变量的变量名。

变量的底层存放实现原理比较复杂,需要一定的操作系统或计算机组成原理知识去加以理解,在后续关于指针的教程中会再次提及,不用担心现在看不懂。

变量的类型

局部变量:在局部作用域定义的普通变量。

void func()
{
    int local_1;     // 存在函数局部作用域内
    {
        int local_2; // 存在规定的局部作用域内(也存在函数局部作用域内)
    }
}

注意:作用域将会在后续中再次提及说明,在此你可以简单的理解为在{}运算符内即为在某个作用域内。

全局变量:定义在所有函数体外,与上述相反,不存在于任何函数或其他规定的作用域内。

int global; // 不存在于任何作用域内

静态变量:使用static关键字修饰的变量(包含全局变量与静态变量)

static int static_global;    // 静态全局变量
void func()
{
    static int static_local; // 静态局部变量
}

变量的定义与初始化

变量的初始化是在定义变量的同时为其赋予一个初始值。变量的初始化可以在定义时进行,也可以在后续的代码中进行。

type variable_list; => 数据类型 一个或多个变量的名称组成

int a;              // 定义未初始化
a = 0;              // 变量初始化
int i, j, k, m = 0; // 直接初始化
int *ptr = NULL;    // 直接初始化

注意:

  • 全局变量与静态变量若未显式初始化会自动初始化为类型默认值
  • 局部变量不会自动初始化,未初始化时指向栈上一个随机值
  • 使用未初始化的变量极其危险,局部变量一定记得初始化

静态变量的初始化与使用的经典代码案例:

// part 1
static int static_i = 0;
while (x--)
{
    static int static_i = 0;
    static_i++;
}
printf("%d\n", static_i);

// part 2
int res;
int x = 10;
while (x--)
{
    static int static_i = 0;
    res = ++static_i;
}
printf("%d\n", res);

初识左值与右值

左值与右值的定义是C语言乃至C++语言都较为灵魂的存在,千言万语不足以概括其特点与应用场景,在此旨在用最简短的语言说明。

左值:可以出现在 = 的左边或右边,有内存、有名字、非临时。

// 变量a、变量b都是左值
int a = 0;
int b = a;
a = b;

右值:只可以出现在“=”的右边,有内存、无名字、临时。

// 变量a是左值,而10、20是立即数,为右值
int a = 10;
a = 20;
// 10 = 20
// 20 = 10

立即数:一个立即数是一块数据存储作为指令本身,而不是在一个中的一部分内容存储器位置或寄存器。(操作系统知识、不理解算了)

常量的类型

常量是固定值,在程序执行期间不会改变。这些固定的值,又叫做字面量。

整数常量(尾缀不区分大小写)

进制类型表达方式
十进制1234
无符号十进制1234u
长十进制1234l
八进制02322
十六进制0x4D2

浮点常量(尾缀不区分大小写)

表达类型表达方式
小数表达3.1415 或 3.1415f
指数表达31415e-4

注意:尾缀表示当前数的类型,其中u(无符号数)、l(长整型)、f(单精度浮点型)、e(10的次幂)等。

字符常量

把字符放在单引号内,例如 'a' 。字符常量里面存在 \反斜杠时可能会与后面的字符结合发生转移,组合类型可以去查询其他资料。

字符串(字符数据常量)

把字符放在双引号内,例如 "abcd"

char myString[] = "Hello World!";

系统会对字符串自动在末尾加’\0’表示字符终止。

常量的定义

使用 #define 预处理器,一般放在程序代码开头或者头文件中。

#define PI 3.1415
#define ENDL '\n'
printf("%f", PI);
printf(ENDL);

使用 const 关键字进行定义,实现语言级别定义的常量。常量必须初始化且不能被修改(理论上,实际上在C语言中可以操纵指针修改)

const int MY_MIN_INT = -1;

运算符、判断、循环

程序的臂膀:运算

算数运算符:+、-、*、/、%、++、–

int a = 10;
int b = 20;
int c = 0;
c = a + b; // 加法
c = a - b; // 减法
c = a * b; // 乘法
c = a / b; // 取整
c = a % b; // 取余
a++;       // 后自加
++a;       // 前自加(效率高)

关系运算符:==、!=、>、>=、<、<=

int a = 10;
int b = 20;
a == b;
a != b;
a > b;
a >= b;
a < b;
a <= b;

逻辑运算符:&&、||、!

int A = 1;
int B = 0;
A &&B;    // 逻辑与,都真才为真
A || B;   // 逻辑或,存在真则为真
!(A &&B); // 逻辑非,转换状态

位运算符:&、|、^、~、<<、>>(难点、难理解)参考链接

赋值运算符(赋值运算符、运算符+赋值运算符、位运算符+赋值运算符)

例如:=、+=、&=、<<=等,表达意思即为 左 = 左 操作 右

杂项运算符:sizeof、&、*、三目(三元)运算符

int intSize = sizeof(int); // 返回变量大小
int *ptr = &A;             // 返回变量的地址
B = *ptr;                  // 指向ptr指针存放地址上的变量(指针解引用)
B = (B == 0) ? 0 : 1;      // 三元运算符 条件?条件为真的结果:条件为假的结果,表意如下
if (B == 0){B = 0;}else{B = 1;}

运算符优先级

不用刻意记忆,多加使用即可,拿不定的地方用 ()

程序的大脑:判断

C语言原生不支持布尔(bool)类型,因此C语言中0表示为false,其余表示为true。

if 语句

if (0) // 判断条件,为真进入语句(作用域),为假不进入语句
{
    // 语句……
}

if-else 语句

if (0) // 判断条件,为真进入if语句(作用域),为假进入else语句
{
    // 语句……
}
else
{
    // 语句……
}

嵌套if 语句

if (0)
{
    if (1)
    {
        // 语句
    }
}

switch 语句

一个 switch 语句允许测试一个变量等于多个值时的情况。每个值称为一个case,且被测试的变量会对每个 switch->case 进行检查。

enum DAY // 定义枚举变量
{
    MON = 1,
    TUE,
    WED,
    THU,
    FRI,
    SAT,
    SUN
};
enum DAY day = SUN;
switch (day) // 传入测试变量,测试分支的数据类型需要相同
{
case SAT: // 测试分支
    printf("REST");
    break; // 如果满足此测试分支,完成语句后退出测试,不退出将会继续执行下面的测试
case SUN:
    printf("REST");
    break;
default: // 默认测试分支
    printf("WORK");
}

嵌套switch 语句

使用场景很少,使用逻辑等同于嵌套if语句。

程序的双脚:循环

while 循环

while (0) // 判断为真进入语句,判断为假结束循环
{
    // 语句
}

for 循环

int x = 0;
for (int i = 0; i < 2; ++i)
{
    // 语句
}

for循环内三个控制量:for ( init ; condition ; increment ) {}

init:最先执行且只执行一次,通常用于初始化循环控制变量,可留白;

condition:控制主体,为真执行循环内语句,为假结束循环,可留白;

increment:增量主体,在每次循环最后执行,一量般用于更新控制变,可留白;

特殊用法——无限循环/死循环

for( ; ; ) {}

do while循环(不常用)

与while循环相似,但确保循环内语句至少执行一次。

do
{
    // 语句
} while (0);

嵌套循环

用法与判断嵌套相似,注意循环控制变量,防止死循环。

// 嵌套for循环
for (int i = 0; i < 10; ++i)
{
    for (int j = 0; j < 10; ++j)
    {
    }
}

// 嵌套while循环
while (0)
{
    while (0)
    {
    }
}

// 互相嵌套
while (1)
{
    for (int i = 0; i < 10; ++i)
    {
        while (0)
        {
        }
    }
}

循环控制语句

break:终止循环或switch语句,继续执行其下一条语句。

while (1)
{
    printf("触发死循环\n");
    break;
}

continue:终止此次循环,重新开始下次循环。

循环控制经典案例:

int i = 5;
while (i--) // 先赋值(判断)再减减
{
    printf("%d\n", i);
    if (i % 2 == 0)
    {
        continue;
    }
    printf("%d\n", i);
}

i = 5;
while (--i) // 先减减再赋值(判断)
{
    printf("%d\n", i);
    if (i % 2 == 0)
    {
        continue;
    }
    printf("%d\n", i);
}

goto:控制转移(不建议使用)。


函数、作用域、头文件


函数:一组一起执行一个任务的语句。

  • 每个 C 程序都至少有一个函数,即主函数 main() ;
  • 所有简单的程序都可以定义其他额外的函数;
  • 函数还有其他叫法、例如方法、子例程、程序等。

函数的声明

函数的声明告诉编译器函数的名称参数列表函数返回值类型,即告诉编译器如何调用函数,其主体可以单独定义。

int max(int a, int b); // 函数声明

注意:函数声明中,参数的名称不重要,类型是必须的。

函数的定义

函数的定义提供了函数的实际主体。

int max(int a, int b) // 返回值类型 函数名(参数列表)
{ 
	// 函数主体
    if (a >= b)
    {
    	// 函数返回语句
        return a;
    }
    else
    {
    	// 函数返回语句
        return b;
    }
}

函数的参数与返回值

传入
如果函数要使用参数,则必须声明接受参数值的变量。这些变量称为函数的形式参数
形式参数就像函数内的其他局部变量,在进入函数时被创建,退出函数时被销毁
返回
返回一个形参时,会在主函数栈临时在创建一个临时变量用以返回值的其他操作,调用函数的语句结束时,该临时变量生命周期结束

函数的传值方式

经典的两数交换问题
值传递:该方法把参数的实际值复制给函数的形式参数。在这种情况下,修改函数内的形式参数不会影响实际参数。

void swap_error(int a, int b)
{
    int temp = a;
    a = b;
    b = a;
}

函数调用:

int a = 10;
int b = 20;
swap_error(a, b);
printf("a = %d, b = %d\n", a, b);

结果显而易见,是无法完成两数交换的。

指针传递:通过指针传递方式,形参为指向实参地址的指针,当对形参的指向操作时,就相当于对实参本身进行的操作。

// 指针传递
void swap_real(int *a, int *b)
{
    int temp = *a;
    *a = *b;
    *b = temp;
}

函数调用:

int a = 10;
int b = 20;
swap_real(&a, &b);
printf("a = %d, b = %d\n", a, b);

利用指针传递变量的地址,通过指针解引用,进而直接对该指针存放的地址上的变量操作(交换),能够实现两数交换。

作用域

作用域是程序中定义的变量所存在的区域,超过该区域变量就不能被访问。

  • 在函数或块内部的局部变量(简而言之就是{}之内的变量)
  • 在所有函数外部的全局变量(简而言之就是独立于所有函数体的变量)
  • 在形式参数的函数参数定义中(简而言之就是函数的形式参数变量)

在本文的变量部分处已作详细解释。

头文件

头文件是扩展名为 .h 的文件,包含了 C 函数声明和宏定义,被多个源文件中引用共享。
有两种类型的头文件:程序员编写的头文件和编译器自带的头文件。
在程序中要使用头文件,需要使用 C 预处理指令 #include 来引用它。
#include <系统头文件>
#include "用户头文件/系统头文件"
使用双引号则会优先引用用户头文件。
注意:一个文件中某一个头文件只能被引用一次,否则会发生错误。
标准的做法是把整个头文件放在条件编译语句中,如下所示:

#ifndef HEADER_FILE // 包装器可以进行判断是否引用,为真则直接跳过到endif中间的全部内容
#define HEADER_FILE

// 完整的头文件内容

#endif

头文件是在C语言中高频使用的编程文件,能够让程序更加直观简洁,同时利用头文件编译等技术能够将关键的程序代码保护起来,增强代码不可见性。

结构体、共用体



指针、数组、字符串、输入输出流、内存管理



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 掌握C语言的最佳方式是通过阅读书籍、观看视频教程、做练习题以及动手实践去习。首先,可以从一本入门书籍开始,然后通过搜索引擎找到一些在线教程或视频,以及一些相关的练习题以及示例代码,加上不断的实践和持续的努力,你就可以掌握C语言啦! ### 回答2: C语言的关键在于掌握基础知识和进行实践。下面是一些建议,帮助小白快速C语言。 首先,小白可以通过读取C语言的教材来了解基本语法和概念。选择一本通俗易懂、有实例讲解的教材,可以帮助小白迅速入门。此外,互联网上也有许多免费的C语言教程和教视频,小白可以利用这些资源来习。 其次,小白习的过程中,要注重实践。通过编写简单的程序来巩固所知识,例如编写输出Hello World的程序、实现计算器等。可以从简单的程序开始,逐渐增加难度,逐步提高自己的编程能力。 第三,小白可以加入一些C语言习群组或论坛,与其他C语言爱好者交流。在这些群组中,可以向其他人请教问题、讨论习进展,获取更多有关C语言的经验和技巧。 此外,小白还可以参与一些C语言的项目,如开源社区。通过参与实际的项目,可以锻炼自己的编程能力,提高解决问题的能力。 最后,要坚持习。习编程需要持之以恒的努力和耐心。小白可以制定一个合理的习计划,每天保持一定的习时间。并且,要养成良好的编程习惯,包括注释代码、规范命名等。 总的来说,小白C语言,需要具备基础知识、进行实践、积极参与社区和项目、坚持习。通过不断地习和实践,小白一定可以快速掌握C语言。 ### 回答3: 要想快速C语言小白可以考虑以下几个方法。 首先,掌握基本概念。让自己熟悉C语言的基本语法规则、数据类型、变量和运算符等基本概念。可以通过阅读相关教材或者网上的教程来习。 其次,进行实践操作。通过实际编写程序来加深理解和掌握C语言。可以从简单的程序开始,逐步增加难度和复杂度。可以尝试解决一些小的编程问题,或者参与开源项目,这样能够锻炼和提高自己的编程能力。 另外,多参加编程交流和讨论。可以加入一些C语言的在线交流群或者论坛,与其他同交流习经验,分享问题和解决方案。通过与他人交流,能够获得更多的灵感和思路,也能够迅速纠正习中的错误。 此外,阅读优秀的源代码也是一个非常有效的习方法。可以关注一些开源的C语言项目,阅读他们的源代码,并且尝试理解其中的实现原理和设计思路。通过借鉴他人的经验,能够提高自己的编程水平。 最后,保持坚持和不断习的态度。习编程需要时间和耐心,需要不断地进行实践和总结。在习过程中,可能会遇到一些困难和挫折,但只要保持积极的态度,坚持下去,一定能够取得进步和提高。 总的来说,快速C语言需要了解基本概念、进行实践操作、参加交流讨论、阅读源代码,并且保持坚持和不断习的态度。不仅要会语法和概念,还要锻炼实践能力和问题解决能力。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值