当前位置:   article > 正文

【初级】1. 初识C语言——快速入门_鹏哥c语言快速入门

鹏哥c语言快速入门


文章说明:该文章的知识点源于B站上比特鹏哥的C语言课程,结合鹏哥上课的讲义、课堂代码以及自己的理解整理形成。

VS2019按F10进行代码调试。监视窗口在调试-窗口里面打开;内存窗口在调试-内存里面打开

1. 数据类型

数据类型的作用:创建对应大小的内存空间,以存放数据。

char        //字符数据类型
short       //短整型
int         //整形
long        //长整型
long long   //更长的整形
float       //单精度浮点数
double      //双精度浮点数   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

每种数据类型的大小(内存空间)多少?

#include <stdio.h>
int main()
{
    //sizeof: 关键字 - 操作符 - 计算类型或者变量所占空间的大小
    printf("%d\n", sizeof(char));			//1
    printf("%d\n", sizeof(short));			//2
    printf("%d\n", sizeof(int));			//4
    printf("%d\n", sizeof(long));			//4
    printf("%d\n", sizeof(long long));		//8
    printf("%d\n", sizeof(float));			//4
    printf("%d\n", sizeof(double));			//8
    printf("%d\n", sizeof(long double));	//16
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

注:C语言标准: sizeof(long) >= sizeof(int)

#include <stdio.h>
int main()
{
    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 - 计算元素个数
    //sizeof(arr) 等价于 sizeof arr。所以sizeof不是函数
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

为什么出现这么多数据类型?

答:存在这么多的类型,其实是为了更加丰富的表达生活中的各种值。类型丰富的时候,选择性更多,空间利用率更高(选择最适合当前情况的类型)。

2. 变量和常量

变量:能被改变的量。(局部变量 + 全局变量

常量:不能改变的量。

推荐写法:int age = 20; 即:创建变量的时候赋予初始值

不推荐:int age;

2.1 变量

局部变量和全局变量名字冲突的情况下,局部变量优先写代码时不建议将全局变量和局部变量写成一样的。


作用域:变量可用的代码范围。

局部变量的作用域是变量所在的局部范围。(所属那一层的{}中间)

全局变量的作用域是整个工程。(1次定义,跨文件用extern声明 -> 跨文件全局变量

例:在 a.c 文件中定义全局变量int flag_global = 0;。 在 b.c 文件中用到flag_global时,要先声明:extern int flag_global;

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

局部变量:进入局部范围为生命周期的开始,出局部范围为生命周期的结束。

全局变量:整个程序(main函数)的生命周期。


2.2 常量

  1. 字面常量(无意义)

    3.14;
    10;
    'a';
    "abcdef";
    
    • 1
    • 2
    • 3
    • 4
  2. const 修饰的常变量(本质:变量

    const 修饰变量具有常属性:该变量的值无法被更改。

    const int sum = 10;
    
    • 1
    const int n = 10;
    int arr[n] = {0}; //n为变量,数组的下标必须为常量,这样会报错
    
    • 1
    • 2
  3. #define 定义的标识符常量

    #define Max 1000
    
    • 1
  4. 枚举常量(用于可以一一列举的常量)

    enum Sex 
    {
        //赋初值
        MALE,		//0
        FEMALE,		//1
        SECRET		//2
    }; //括号中的MALE,FEMALE,SECRET是枚举常量。默认从0开始,每次增加1。
    
    enum Sex s = MALE; //定义
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

3. 字符串+转义字符

3.1 字符串

字符串就是一串字符-双引号引起来的一串字符。结束标志:\0

在计算字符串长度的时候\0是结束标志,不算作字符串内容。

#include <stdio.h>
//下面代码,打印结果是什么?为什么?(突出'\0'的重要性)
int main()
{
	char arr1[] = "bit";
	char arr2[] = {'b', 'i', 't'};
	char arr3[] = {'b', 'i', 't', '\0'};
    
	printf("%s\n", arr1);	//bit		 strlen(arr1) = 3
    printf("%s\n", arr2);	//bit+乱码	strlen(arr2) = 随机值
    printf("%s\n", arr3);	//bit	  	 strlen(arr3) = 3
    return 0;
}
//strlen():求字符串长度的函数(不包括结束标志\0)	头文件:string.h
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

3.2 转义字符

转义字符:转变了字符原有的意思。

#include <stdio.h>
int main()
{
    printf("c:\code\test.c\n");	//输出结果 c:code	est.c
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
转义字符释义
\'用于表示字符常量’
\"用于表示一个字符串内部的双引号
\\用于表示一个反斜杠,防止它被解释为一个转义符
\t水平制表符
\r回车
\n换行
\dddddd 表示1~3个八进制的数字。 如: \130 X(ASCII码值是88=\130)
\xdddd 表示2个十六进制数字。 如: \x30 0

ASCII码表:每一个字符(对应printf的%c)都有一个值。 printf("%c\n", '\130');

//程序输出多少?
#include <stdio.h>
int main()
{
    printf("%d\n", strlen("c:\test\628\test.c"));	//输出结果:14
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

4. 注释

// :C++注释风格

/* .......... */ :C语言注释风格 缺陷:不能嵌套注释,遇到第一个*/就结束了。

代码中有不需要的代码可以直接删除,也可以注释掉

代码中有些代码比较难懂,可以加一下注释文字

5. 函数

参数是函数与函数间的交流方式

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

函数的括号无法省略。

6. 数组

数组:一组相同类型元素的集合。使用下标来访问,下标从0开始。

int arr[10] = {1,2,3,4,5,6,7,8,9,10};//定义一个整形数组,最多放10个元素
char ch[5] = {'a', 'b', 'c'};//不完全初始化,剩余的元素默认为0
  • 1
  • 2

7. 操作符

9/2 -> 4
9.0/2 -> 4.5
  • 1
  • 2

[]:下标引用操作符 arr[5][]下标引用操作符。数组定义时的[]不是下标引用操作符。

():函数调用操作符 调用函数的时候,函数后面的()就是函数调用操作符。

7.1 位操作符

~ & | ^(按位异或)

7.2 单目操作符

符号作用
!逻辑反操作(0为假,非0为真)
-负值
+正值
&取地址
sizeof操作数的类型长度(以字节为单位)
~对一个数的二进制按位取反
前置、后置–
++前置、后置++
*间接访问操作符(解引用操作符)
(类型)强制类型转换

整数在内存中存储的是补码。

#include <stdio.h>
int main()
{
    int a = 0;
    printf("%d\n", ~a);	//输出结果:-1
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

前置表达式的值

#include <stdio.h>
int main()
{
    int a = 10;
    int b = ++a; //b的值取决于表达式++a的结果
    printf("%d\n", b);	//输出结果:11
    printf("%d\n", a);	//输出结果:11
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

后置表达式的值

#include <stdio.h>
int main()
{
    int a = 10;
    int b = a++; //b的值取决于表达式a++的结果
    printf("%d\n", b);	//输出结果:10
    printf("%d\n", a);	//输出结果:11
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

7.3 逻辑操作符

&& 逻辑与

|| 逻辑或

! 逻辑非

7.4 条件操作符(三目操作符)

exp1 ? exp2 : exp3

exp1成立,整个表达式的结果为exp2的结果;exp1不成立,整个表达式的结果为exp3的结果

7.5 逗号表达式

exp1, exp2, exp3, … , expN

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

#include <stdio.h>
int main()
{
    int a = 0;
    int b = 3; 
    int c = 5;
    int d = (a = b + 2, c = a -4, b = c + 2); //a=5, c=1, b=3

    printf("%d\n", d);	//输出结果:3
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

8. 关键字

  1. 关键字是C语言提供的,不能自己创建关键字
  2. 关键字不能是变量名

常见关键字:

auto	break	case	char	const	continue	default	do	double	else	enum   
extern	float	for	goto	if	int	long	register	return	short	signed 
sizeof	static	struct	switch	typedef	union	unsigned	void	volatile	while
  • 1
  • 2
  • 3

auto:自动创建,自动销毁。局部变量都是 auto 类型,基本都省略掉auto现如今意义不大)。

register int num = 100; 建议num 的值存放在寄存器中。 大量、频繁被使用的数据,放到寄存器中,提高效率(现如今意义不大)。

defineinclude 不是关键字,属于预处理指令

8.1 typedef

类型重命名 -> 别名

typedef unsigned int uint_32;
  • 1

8.2 static

static是用来修饰变量和函数的

  1. 修饰局部变量 -> 称为静态局部变量
  2. 修饰全局变量 -> 称为静态全局变量
  3. 修饰函数 -> 称为静态函数

static修饰局部变量改变了变量的生命周期

静态局部变量出了作用域依然存在,到程序结束,生命周期才结束本质是改变了变量的存储类型)。

//代码1
#include <stdio.h>
void test()
{
    int i = 0;
    i++;
    printf("%d ", i);
}

int main()
{
    int i = 0;
    for(i=0; i<10; i++)
    {
        test(); //打印10个1
    }
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
//代码2
#include <stdio.h>
void test()
{
    //static修饰局部变量
    static int i = 0;
    i++;
    printf("%d ", i);
}

int main()
{
    int i = 0;
    for(i=0; i<10; i++)
    {
        test(); //打印1 2 3 4 5 6 7 8 9 10
    }
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

一个全局变量被 static 修饰,使得这个全局变量只能在本源文件内使用,不能在其他源文件内使用。

全局变量,在其他源文件内部可以被使用,是因为全局变量具有外部链接属性。但是被 static 修饰后,就变成了内部链接属性,其他源文件就不能链接到这个静态的全局变量了。

//代码1
//add.c
int g_val = 2018;
//test.c
int main()
{
    printf("%d\n", g_val);
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
//代码2
//add.c
static int g_val = 2018;
//test.c
int main()
{
    printf("%d\n", g_val);
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

一个函数被static修饰,使得这个函数只能在本源文件内使用,不能在其他源文件内使用。

本质static 将函数的外部链接属性变成了内部链接属性!(和 static 修饰的全局变量一样)

//代码1
//add.c
int Add(int x, int y)
{
    return c+y;
}

//test.c
int main()
{
    printf("%d\n", Add(2, 3));
    return 0;
} 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
//代码2
//add.c
static int Add(int x, int y)
{
    return c+y;
}

//test.c
int main()
{
    printf("%d\n", Add(2, 3));
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

9. #define 定义常量和宏

define 是一个预处理指令

//define定义标识符常量
#define MAX 1000
  • 1
  • 2
//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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

10. 指针

指针就是地址

32位机器 - 32根地址线 - 物理线 - 通电 - 1/0

一个内存单元是一个字节,然后分配地址。&a 只会拿出第一个字节的地址

int *pa = &a; //pa是存放地址的,存放地址的变量称为指针变量。
  • 1

* 说明pa是指针变量; int 说明pa指向的对象是 int 类型的。

指针变量的大小:

#include <stdio.h>
//指针变量的大小取决于地址的大小
//32位平台下地址是32个bit位(即4个字节)
//64位平台下地址是64个bit位(即8个字节)
int main()
{
    printf("%d\n", sizeof(char *));
    printf("%d\n", sizeof(short *));
    printf("%d\n", sizeof(int *));
    printf("%d\n", sizeof(double *));
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

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

11. 结构体

结构体的目的:有能力描述复杂对象,创造关于复杂对象的新类型。

struct Stu
{
    char name[20];//名字
    int age;      //年龄
    char sex[5];  //性别
    char id[15]//学号
};

int main()
{
    //结构体的创建和初始化
	struct Stu s = {"张三"20"男""20180101"};
    
    //.为结构成员访问操作符
    printf("name = %s age = %d sex = %s id = %s\n", s.name, s.age, s.sex, s.id);
    
    //->操作符  结构体指针->成员变量
    struct Stu *ps = &s;
    printf("name = %s age = %d sex = %s id = %s\n", ps->name, ps->age, ps->sex, ps->id);
    
    //目的同上
    printf("name = %s age = %d sex = %s id = %s\n", (*ps).name, (*ps).age, (*ps).sex, (*ps).id);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/570540
推荐阅读
相关标签
  

闽ICP备14008679号