C语言学习笔记(一):初识C语言

基于B站比特鹏哥视频学习,基本了解C语言基础知识,对C语言有一个大概认识

1. 什么是C语言


人和计算机交流的语言:C/C++/Java/Python/…

C语言广泛应用于底层开发
电脑是一个硬件,在上面安装操作系统:Windows/Linux/Mac
硬件和操作系统之间有一个驱动层
可以在操作系统上安装应用软件
操作系统之上叫上层软件,之下叫底层软件

计算机语言的发展:低级–>高级
二进制的指令–>汇编指令–>B语言–>C语言
C语言的国际标准:ANSI C、C89、C99、C11
其编译器主要有Clang、GCC、WIN-TC、MSVC、Turbo C等

编辑器-编辑
编译器-编译

C/C++是编译型语言
test.c经过编译、链接变为test.exe
Python是解释型语言

2. 第一个C语言程序


采用VS2022

  1. 创建项目
  2. 创建源文件
    .h 头文件(函数的声明、类型的声明、头文件的包含)
    .c 源文件(函数实现)
#include <stdio.h>
int main()
{
    printf("Hello World!");
    return 0;
}

C语言代码中一定要有main函数
main函数也称主函数,是程序的入口有且仅有一个

int main()
{
    return 0;
}

函数正常返回0,异常返回非0

printf是一个库函数,用来打印数据
需要调用stdio.h头文件

  • std-标准
  • i-input
  • o-output

快捷键:

  • ctrl+f5运行代码
  • ctrl+k+c添加注释
  • ctrl+k+u取消注释

.h 头文件:函数的声明、类型的声明、头文件的包含
.c 源文件:函数实现

3. 数据类型


char       //字符数据类型
short      //短整型
int        //整型
long       //长整形
long long  //更长的整型
float      //单精度浮点数
double     //双精度浮点数

计算机中的单位:

  • bit-比特位
  • byte-字节
  • kb
  • mb
  • gb
  • tb
  • pb

十进制的世界:0 1 2 3 4 5 6 7 8 9
二进制的世界:0 1
1个bit存储一个二进制数
1byte=8bit
1kb=1024byte
1mb=1024kb

数据类型的大小(byte):

sizeof(char)      // 1byte
sizeof(short)     // 2
sizeof(int)       // 4
sizeof(long)      // 4
sizeof(long long) // 8
sizeof(float)     // 4
sizeof(double)    // 8

C语言规定:
sizeof(long)>=sizeof(int)

用类型创建变量,向内存申请空间:
int age = 20;
double price = 66.6;

3. 变量、常量


3.1 定义变量的方法

int age = 100;
float weight = 35.5f;
char ch = 'w';

3.2 变量的分类

  • 局部变量
  • 全局变量
int a = 20;     // 全局变量
int main()
{
    int a = 10; // 局部变量
    printf("a=%d\n",a); // a=10
    return 0;
}

全局变量和局部变量的名字可以相同(不建议),局部变量优先

注:VS环境下使用scanf函数时报错,需要在代码第一行加#define _CRT_SECURE_NO_WARNINGS
在VS安装路径下有一个文件:newc++file.cpp
在VS工程中创建新的.c或者.cpp文件的时候,都是拷贝newc++file.cpp的,故在该文件中添加#define _CRT_SECURE_NO_WARNINGS

3.4 变量作用域与生命周期

**作用域(scope)**是程序设计概念,通常来说,一段程序代码中所用到的名字并不总是有效/可用的
而限定这个名字的可用性的代码范围就是这个名字的作用域。

  1. 局部变量的作用域是变量所在的局部范围。
  2. 全局变量的作用域是整个工程(包括所有文件)。
    extern声明外部变量(来自其他文件的变量):extern int a;

变量的生命周期指的是变量的创建到变量的销毁之间的一个时间段

  1. 局部变量的生命周期是:进入作用域生命周期开始,出作用域生命周期结束。
  2. 全局变量的生命周期是:整个程序的生命周期。

3.5 常量

C语言的常量分为以下四种:

  • 字面常量:30;3.14;'w';"abc";
  • const修饰的常变量,本质是变量,但不能直接修改,有常量的属性:const int a = 20;
  • #define定义的标识符常量,不能直接修改:#define MAX 100
  • 枚举常量,不能直接修改
    enum Color //定义枚举类型
    {
        // 枚举常量
        RED,
        GREEN,
        BLUE
    };
    int main()
    {
        enum Color c = RED;
        return 0;
    }
    

4. 字符串+转义字符+注释


4.1 字符串

"hello world\n"
这种由双引号(Double Quote)引起来的一串字符称为字符串字面值(String Literal),或者简称字符串
C语言中没有字符串类型变量

字符串的结束标志:\0
不完全初始化,剩余的部分默认初始化为0
在计算字符串长度的时候\0是结束标志,不算做字符串的内容
打印字符串时遇到\0才停下来

char arr1[] = "abc";
char arr2[] = {'a', 'b', 'c', '\0'};
// 输出相同

求字符串长度的函数strlen(),头文件是<string.h>,遇到\0才停止计算

注意:

  • 0——数字0
  • ‘0’——字符0,ASCII值是48
  • ‘\0’——字符,ASCII值是0
    0和’\0’没有本质区别

4.2 转义字符

转义序列含义
\a警报(ANSI C)
\b退格
\f换页
\n换行
\r回车
\t水平制表符
\v垂直制表符
\\反斜杠(\)
\'单引号
\"双引号
\?问号,在书写连续多个问号时使用,防止被解析成三字母词(古早用法)
\0oo八进制值(oo必须是有效的八进制数,即每个o可表示0~7中的一个数)
\xdd十六进制值(dd必须是有效的十六进制数,即每个d可表示0~f中一个数),如:‘\x63’和’\x063’显示c
\dddddd表示1~3个八进制的数字,如:‘\130’表示’88’,显示X

注:
三字母词:??)–>];??(–>[

A是65,a是97,小写和大写之间差32
ASCII码范围0~127

转义字符算一个字符,在字符串长度中为1
"\628"中,\62被解析成一个转义字符,八进制数字是0~7,所以长度为2,8是一个单独字符
\t是一个字符,效果相当于四个字符,但是不能用于长度计算

5. 注释


  1. 代码中有不需要的代码可以直接删除,也可以注释掉
  2. 代码中有些代码比较难懂,可以加注释文字

C语言注释风格(/* */)不支持嵌套注释,最好还是用C++风格的(//),可以注释一行或多行

6. 选择语句


  • if-else语句
  • switch语句

7. 循环语句


  • while语句
  • for语句
  • do-while语句

C语言是“结构化”的程序设计语言

  • 顺序结构
  • 选择结构
  • 循环结构

8. 函数


函数的特点就是简化代码,代码复用。

#include <stdio.h>
int main()
{
    int num1 = 0;
    int num2 = 0;
    int sum = 0; 
    printf("输入两个操作数:>"); 
    scanf("%d %d", &num1, &num2); 
    sum = num1 + num2; 
    printf("sum = %d\n", sum); 
    return 0;
}

// 上述代码,写成函数如下:
#include <stdio.h>
int Add(int x, int y)
{
    int z = x+y;
    return z;
}

int main()
{
    int num1 = 0;
    int num2 = 0;
    int sum = 0; 
    printf("输入两个操作数:>"); 
    scanf("%d %d", &num1, &num2); 
    sum = Add(num1, num2); 
    printf("sum = %d\n", sum); 
    return 0;
}

其中,int是返回类型,Add是函数名,(int x,int y)是函数参数,{}包含的内容是函数体

9. 数组


9.1 数组定义

int arr[10] = {1,2,3,4,5,6,7,8,9,10};//定义一个整形数组,最多放10个元素

C99之前,数组的大小只能用常量或者常量表达式指定
C99之后,支持变长数组,允许数组的大小是变量,但这种指定方式的数组不能初始化
VS不支持变长数组

9.2 数组的下标

数组的每个元素都有一个下标,下标从0开始
数组可以通过下标来访问
int arr[10] = {0}; //该数组有10个元素,下标范围为0-9

9.3 数组的使用

#include <stdio.h>
int main()
{
    int i = 0;
    int arr[10] = {1,2,3,4,5,6,7,8,9,10}; 
    for(i=0; i<10; i++)
    {
        printf("%d ", arr[i]);
    } 
    printf("\n"); 
    return 0;
}

注:在线OJ(online judge)
很多互联网公司在笔试环节采用在线OJ的形式,题目一般分为两类:

  1. IO型:所有代码由自己完成和实现,输入,计算,输出
  2. 接口型:只需要完成一个函数,其他需要的数据都是准备好的

EOF指end of file,是文件的结束标志,值是-1

下面代码的结果是:随机值

#include <stdio.h>
#include <string.h>
int main()
{
    char arr[] = {'b', 'i', 't'};
    //[b i t ...],在什么时候遇到\0不清楚
    printf("%d\n", strlen(arr));
    return 0;
}

如果arr[4](不完全初始化,剩余值默认为0),则长度为3

10. 操作符


算术操作符

+ - * / %

取模操作符两端只能是整数

移位操作符

>> <<

涉及二进制运算

位操作符

& ^ |

赋值操作符

= += -= *= /= &= ^= |= >>= <<=

单目操作符:只有一个操作数的操作符

操作符功能
!逻辑反操作
-负值
+正值
&取地址
sizeof操作数的类型长度(以字节为单位),括号内可以是变量或类型,可以写成sizeof a,但不可以写成sizeof int
~对一个数的二进制按位取反
前置、后置–
++前置、后置++
*间接访问操作符(解引用操作符)
(类型)强制类型转换

注:

  1. C语言中,0表示假,非0表示真
  2. int arr[10] = {0};
    printf("%d\n",sizeof(arr)); // 40,计算的是整个数组的大小,单位为字节
    printf("%d\n",sizeof(arr[0]));// 4
    printf("%d\n",sizeof(arr)/sizeof(arr[0]));// 10,数组的元素个数
    
  3. 字面浮点数,编译器默认理解为double型

关系操作符

> >= < <= != ==

逻辑操作符:逻辑与、逻辑或

&&、||

条件(三目)操作符:exp1如果为真,计算exp2,否则计算exp3

exp1 ? exp2 : exp3

逗号表达式

exp1, exp2, exp3, …, expN

逗号隔开的一串表达式,特点是从左向右依次计算,整个表达式的结果是最后一个表达式的结果

int main()
{
    int a = 10;
    int b = 20;
    int c = 0;
    //       c=8      a=28     c=5
    int d = (c = a-2, a = b+c, c-3);
    printf("%d\n", d); // 5
    return 0;
}

下标引用、函数调用和结构成员

[ ] ( ) . ->

int main()
{
    int arr[10] = {1,2,3,4,5,6,7,8,9,10};
    arr[3] = 20; // []是下标引用操作符,arr和3是[]的操作数
    return 0;
}

11. 常见关键字


变量的命名:

  1. 有意义
    int age;
  2. 名字必须是字母、数字、下划线组成,不能有特殊字符,不能以数字开头
  3. 变量名不能是关键字
    请添加图片描述
  • auto:自动,所有局部变量前都会有auto,会被省略
  • enum:枚举
  • struct:结构体
  • union:联合体(共用体)
  • extern:声明外部符号
  • return:函数返回值
  • signed:有符号的
  • unsigned:无符号的
  • typedef:类型重命名
  • void:无(函数的返回类型,函数参数)
  • volatile:操作系统中会讲

以下先介绍几个:

11.1 typedef:类型重命名

typedef unsigned int unit;将unsigned重命名为unit

11.2 static:修饰变量和函数

11.2.1 修饰局部变量:称为静态局部变量
#include <stdio.h>

void test1()
{
    int a = 1;
    a++;
    printf("%d ", a);
}

void test2()
{
    static int a = 1;
    a++;
    printf("%d ", a);
}

int main()
{
    int i = 0;
    while (i < 10)
    {
        test1();
        i++;
    }
    // 2 2 2 2 2 2 2 2 2 2 2
    printf("\n");
    i = 0;
    while (i < 10)
    {
        test2();
        i++;
    }
    // 2 3 4 5 6 7 8 9 10 11
    return 0;
}

static修饰局部变量时,局部变量出了作用域,不销毁
本质上static修饰局部变量时,改变了变量的存储位置,影响了变量的生命周期,使其生命周期和程序一样。
请添加图片描述

11.2.2 修饰全局变量

全局变量具有外部链接属性
编译+连接–>可执行程序
全局变量在其他源文件内定义,如果加了static修饰,全局变量的外部链接属性会变成内部链接属性,其他源文件(.c)就不能使用这个全局变量
请添加图片描述
编译不了,全局变量的作用域变小了
全局变量也放在静态区

11.2.3 修饰函数

函数也具有外部链接属性,可以用extern链接
请添加图片描述

函数被static修饰时,外部链接属性变成内部链接属性,其他源文件无法使用
请添加图片描述

11.3 register:寄存器

电脑上的存储设备有:

  • 寄存器(集成到CPU上)
  • 高速缓存(cache)
  • 内存
  • 硬盘
    请添加图片描述

CPU是中央处理器,所有的计算都由CPU处理

创建寄存器变量

int main()
{
	// 寄存器变量
	register int num = 3; // 建议3存放在寄存器中
	return 0;
}

这样对num的访问速度会更快一些
register只是建议,不能决定
只有编译器能决定该变量是否被放到寄存器中

12. #define定义常量和宏


//define定义标识符常量
#define MAX 1000

//define定义宏
#define ADD(x, y) ((x)+(y))

#include <stdio.h>
int main()
{
    int sum = ADD(2, 3);
    printf("sum = %d\n", sum);
    sum = 10*ADD(2, 3);
    printf("sum = %d\n", sum);
    return 0;
}

define不是关键字,是预处理指令
宏有参数
ADD是宏名,xy是宏的参数,参数是无类型,( )是宏体
int c = ((a)+(b));
替换作用

13. 指针


13.1 内存

内存是电脑上特别重要的存储器,计算机中程序的运行都是在内存中进行的

为有效使用内存,把内存划分成一个个的内存单元(一个内存单元的大小:1字节byte

每个内存单元都有一个编号

一个32位电脑
地址线会产生电信号1/0,32根地址线同时产生电信号:一个 2 32 2^{32} 232的可能序列作为地址
4,294,967,296 byte
4,194,394 kb
4096 MB
4 GB
请添加图片描述

1字节byte有8比特bit

int main()
{
    int a = 10;// 向内存申请4个字节存储10
    &a;// 取地址操作符
    // a的地址是第一个字节的地址
    return 0;
}

请添加图片描述

10进制:0~9
8进制:0~7
16进制:0~9 a b c d e f

倒着存:看内存的时候倒着往回看,暂时先这么理解

打印地址:%p
printf("%p\n",&a);
用十六进制打印最方便

如果要把地址存起来
int* p = &a;
p是一个指针变量

内存单元有编号,编号就是地址,也被称为指针
把存放指针/地址的变量称为指针变量

int a = 10;
int* p = &a;

*说明p是指针变量,int说明p指向的对象是int类型
请添加图片描述

char ch = 'w';
char* p = &ch;

*p = 20;解引用操作符通过p中存放的地址,找到p所指向的对象*p就是p指向的对象
这里将p指向的对象a的值改为20

口头上说p是个指针,意思是p是个指针变量

13.2 指针变量的大小

不管是什么类型的指针,都是在创建指针变量
指针变量是用来存放地址的,一个指针变量的大小取决于一个地址存放的时候需要多大空间
32位机器上的地址:32bit位——4byte,所以指针变量的大小是4byte
64位机器上的地址:64bit位——8byte,所以指针变量的大小是8byte

printf("%zd\n", sizeof(char*));
printf("%zd\n", sizeof(int*));
printf("%zd\n", sizeof(double*));

结果都是8

结论:指针大小在32位平台是4个字节,64位平台是8个字节

14. 结构体


结构体把一些单一类型组合在一起,构成新类型
例:描述一个人

struct Stu
{
    char name[20];
    int age;
    char sex[10];
    char tele[12];
};

void print(struct Stu* ps)
{
    printf("%s %d %s %s\n", (*ps).name, (*ps).age, (*ps).sex, (*ps).tele);
    // 结构体指针变量->成员名
    printf("%s %d %s %s\n", ps->name, ps->age, ps->sex, ps->tele);
}

int main()
{
    struct Stu s = {"Zhangsan", 20, "nan", "110"};
    // 结构体对象.成员名
    printf("%s %d %s %s\n", s.name, s.age, s.sex, s.tele);
    print(&s);
    return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值