C语言初阶学习复盘

1、初始C语言

1.1、数据类型

        整型 int、short、long、long long

        字符 char

        浮点型 float、double 

1.2、变量常量

        变量分全局变量和局部变量,局部变量只在所在的作用域有效,出了作用域无效

        int a=0

        float b=5.5

        char ch='a'

        常量:字面常量、const修饰的常变量、#define定义的标识符常量、枚举常量

enum Sex
{
 MALE,
 FEMALE,
 SECRET
};
//括号中的MALE,FEMALE,SECRET是枚举常量
int main()
{
    3.14;//字面常量
    1000;//字面常量
    const float pai = 3.14f;   //const 修饰的常量,const在调试一章会着重讲
    pai = 5.14;//ok?
 #define MAX 100            //#define的标识符常量    
    return 0;
}

1.3、字符串

        “hello world"

        字符串的结束标志是\0

1.4、转义字符

        常用的如注释符//、/**/

        换行符\n

        结束标志\0

        

2、分支与循环

2.1、分支语句

        if……else……语句

int main()
{
	int a = 0;
	scanf("%d", &a);
	if (a == 0)
	{
		printf("吃饭\n");
	}
	else
	{
		printf("喝水\n");
	}
	return 0;
}

        switch……case……语句

int main()
{
	int a = 0;
	scanf("%d", &a);
	switch (a)
	{
	case 1:
		printf("星期一\n");
		break;
	case 2:
		printf("星期二\n");
		break;
	case 3:
		printf("星期三\n");
		break;
	case 4:
		printf("星期四\n");
		break;
	case 5:
		printf("星期五\n");
		break;
	case 6:
		printf("星期六\n");
		break;
	case 7:
		printf("星期日\n");
	}
	return 0;
}

2.2、循环语句

while

int main()
{
	int a = 0;
	while (a < 5)
	{
		printf("%d ", a);
		a++;
	}
	return 0;
}

for(;;)

int main()
{
	int a = 0;
	for (a = 0; a < 5; a++)
	{
		printf("%d ", a);
	}
	return 0;
}

do while

int main()
{
	int a = 0;
	do
	{
		printf("%d ", a);
		a++;
	} while (a < 5);
	return 0;
}

continue:是用于结束结束本次循环continue后面的所有代码的,直接跳转到循环开始的部分开始下一次循环

break:终止循环

2.3、go to语句

go to语句适用于在多层嵌套的程序中,用于跳转到指定的位置,完成continue和break无法完成的动作

for(...)
    for(...)
   {
        for(...)
       {
            if(disaster)
                goto error;
       }
   }
    …
error:
 if(disaster)//处理错误情况

3、函数

3.1、函数分为库函数和自定义函数,使用库函数时需要有对应的#include开头的头文件;

        自定义函数是自己定义的函数。如更换两个变量内容的函数

void swap(int *pa, int *pb)//该函数设计到指针的调用,形参与实参
{
	int tmp = 0;
	tmp = *pa;
	*pa = *pb;
	*pb = tmp;
}
int main()
{
	int a = 3;
	int b = 5;
	swap(&a, &b);
	printf("a=%d b=%d\n", a, b);
	return 0;
}

3.2、形参与实参

        形参实例化后相当于实参的一份临时拷贝,他们使用的不是同一块内存空间。

3.3、函数的调用

        传值调用:函数的实参和形参分别占用不同的内存块,对形参的修改不会影响实参

        传址调用:把函数外部创建的变量的地址传给函数参数的调用方式,这种方式可以在函数内操作函数外部的变量,如上面更换两个变量内容的函数就是传址调用。

3.4、嵌套调用和链式访问

        嵌套调用:可以在函数内部调用函数

void swap1()
{
	printf("hello");
}
void swap2()
{
	swap1();
}
int main()
{
	swap2();
	return 0;
}

        链式访问:把一个函数的返回值作为另一个函数的参考

int main()
{
	char arr[20] = "hello";
	int ret = 0;
	ret = strlen(strcat(arr,"bit"));//strcat(arr1,arr2)是将arr2所指向的字符串内容加到arr1后面去的库函数,头文件#include <string.h>
	printf("%d\n", ret);
	return 0;
}

3.5、函数的声明和定义

        函数需要先声明再使用,另外关于函数的深入学习会涉及到模块化。

3.6、函数的递归

函数自己调用自己,将大事化小的解决方法

int strlen(const char* str)//被const修饰的*str内容不可改变
{
	if (*str == '\0')
		return 0;
	else
		return 1 + strlen(str + 1);
}
int main()
{
	char* p = "abcde";
	int len = strlen(p);
	printf("%d\n", len);
	return 0;
}

4、数组

4.1、不管是一维数组还是二维数组,在内存中的存储方式都是连续的。

4.2、数组传参时,数组名(如arr[])一般代表的是数组首元素的地址,另外有两个例外:sizeof(数组名)计算的是整个数组的大小;&数组名取出的是整个 数组的地址

5、操作符

5.1、算数操作符:+、-、*、/、%

5.2、位移操作符

        左移操作符<<

int main()
{
	int a = 1;		//00000000000000000000000000000001
	a = a << 1;		//00000000000000000000000000000010
	printf("%d\n", a);
	return 0;
}

        右移操作符>>

int main()
{
	int a = 5;		//00000000000000000000000000000101
	a = a >> 1;		//00000000000000000000000000000010
	printf("%d\n", a);
	return 0;
}

5.3、位操作符

        按位与&

int main()
{
	int a = 5;		//00000000000000000000000000000101
	int b = 3;		//00000000000000000000000000000011
	int c = a & b;	//00000000000000000000000000000001
	printf("%d\n", c);
	return 0;
}

        按位或

int main()
{
	int a = 5;		//00000000000000000000000000000101
	int b = 3;		//00000000000000000000000000000011
	int c = a | b;	//00000000000000000000000000000111
	printf("%d\n", c);
	return 0;
}

按位异或^

int main()
{
	int a = 5;		//00000000000000000000000000000101
	int b = 3;		//00000000000000000000000000000011
	int c = a ^ b;	//00000000000000000000000000000110
	printf("%d\n", c);
	return 0;
}

5.4、逻辑操作符

        逻辑与:当运算符两边的表达式都为真时结果为真,当运算符左边为假时,右边便不再运算

int main()
{
	int a = 0;		
	int b = 3;		
	int c = a || b;	
	printf("%d\n", c);
	return 0;
}

        逻辑或:表达式两边有一个为真即为真,当运算符左边为真时,右边将不再运算

int main()
{
	int a = 0;		
	int b = 3;		
	int c = a && b;	
	printf("%d\n", c);
	return 0;
}

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

        (exp1?exp2:exp3),即exp1若为真,则整个表达式结果为exp2,否则为exp3

int main()
{
	int a = 0;		
	int b = 3;		
	int c = (a > b ? a : b);
	printf("%d\n", c);
	return 0;
}

5.5、单目操作符

! 逻辑反操作

& 取地址

* 间接访问操作符

sizeof 操作数的类型长度

~ 取反

void test1(int arr[])
{
	printf("%d\n", sizeof(arr));
}
void test2(char ch[])
{
	printf("%d\n", sizeof(ch));
}
int main()
{
	int arr[10] = { 0 };
	char ch[10] = { 0 };
	printf("%d\n", sizeof(arr));//40,sizeof(数组名)求的是数组所占字节大小,每个整型占4个字节,字符占1个字节
	printf("%d\n", sizeof(ch));//10
	test1(arr);//4,数组传参传过去的是数组首元素的地址,本质上函数内求得都是首元素指针的大小,都为4
	test2(ch);//4
	return 0;
}

5.6、逗表达式号

(exp1,exp2,exp3……expn)从左到右依次执行,结果为最后一个表达式结果

int main()
{
	int a = 0;		
	int b = 3;		
	int c = (a++,b++,a+b);
	printf("%d\n", c);
	return 0;
}

5.7、访问结构成员

结构体.成员名

结构体指针->成员名

在结构体一章会详细介绍

5.8、整型提升

计算机在进行运算时,一般会将数据长度提升到整型大小运算,再将运算结果截断成所需的长度。

如char a=-1会在前面补上符号位,变为11111111111111111111111111111111

char b=1为00000000000000000000000000000001

6、指针

6.1、什么是指针

        指针内存放的是地址,通过指针可以找到地址所对应的值

6.2、指针类型

        指针也分类型,不同类型的指针用于存放不同类型的数据

6.3、野指针

        野指针即指针指向位置不可知(随机的、不正确的、没有明确限制的)

        指针未初始化

int main()
{
	int* p;//指针未初始化,没有明确指向的区域
	*p = 1;
	return 0;
}

        指针越界访问

int main()
{
	int arr[10] = { 0 };
	int* p = arr;
	int i = 0;
	for (i = 0; i < 12; i++)
	{
		*(p + i) = arr[i];//当i超过10时,指针p+i指向的便不再是数组arr的元素
	}
	return 0;
}

        指针指向的空间释放(在动态内存开辟讲解)

6.4、指针±整数

int main()
{
	int n = 10;
	char* pc = (char*)&n;
	int* pi = &n;

	printf("%p\n", &n);//00DBFA54
	printf("%p\n", pc);//00DBFA54
	printf("%p\n", pc + 1);00DBFA55
	printf("%p\n", pi);//00DBFA54
	printf("%p\n", pi + 1);//00DBFA58
	return  0;
}

因为指针类型的不同,指针加减整数时在内存中前进的字节也不同

6.5、指针 - 指针

        可用于计算数组大小

int my_strlen(char* str)
{
	char* start = str;
	while (*str != '\0')
	{
		str++;
	}
	return str - start;
}
int main()
{
	char arr[] ="abcdef";
	printf("%d\n",my_strlen(arr));
	return  0;
}

数组元素的指针可以与数组最后一个元素后面的元素比较,但不允许与首元素前面的元素相比较

6.6、指针和数组

        数组首元素的地址就是数组地址,通过对指针的加减,可以实现对数组元素的访问

int main()
{
	int arr[] = { 1,2,3,4,5,6,7 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	int* p = arr;
	int i = 0;
	for(i = 0; i < sz; i++)
	{
		printf("&arr[%d]=%p<===>p+%d=%p\n",i,&arr[i],i,p+i);
	}
	return 0;
}

6.7、二级指针

        指针变量也是变量,所以可以使用二级指针存放指针变量的地址,如若int a的地址为0x0040ff84,*pa=&a,pa的地址为0x0044ff32,**ppa=*pa指向的就是pa的地址0x0044ff32

6.8、指针数组

        指针数组也是数组,只是数组中存放的是指针

int main()
{
	int arr[5] = { 0 };
	int a = 1;
	int b = 2;
	int c = 3;
	int d = 4;
	int e = 5;
	int* arr2[5] = { &a,&b,&c,&d,&e };
	int i = 0;
	for (i = 0; i < 5; i++)
	{
		printf("%d ", *arr2[i]);
	}
	return 0;
}

7、结构体初阶

7.1、声明结构体

struct Stu
{
	char name[20];
	int age;
	int score;
};

7.2、创建结构体变量

struct point
{
	int x;
	int y;
}p1;//创建结构体时创建变量
struct point p2 = { 3,5 };//直接创建结构体变量
struct node
{
	int data;
	struct point p;
}n1 = { 1,{3,2} };
struct node n2 = { 4,{3,1} };//结构体嵌套初始化

7.3、结构体成员的访问

struct Stu
{
	char name[20];
	int age;
	int score;
};
void print(struct Stu* ps)
{
	printf("name=%s age=%d score=%d\n", (*ps).name, (*ps).age, (*ps).score);
	printf("name=%s age=%d score=%d\n", ps->name, ps->age, ps->score);//使用结构体指针访问结构体成员
}
int main()
{
	struct Stu s = { "张三",15,90 };
	print(&s);//结构体地址传参
	return 0;
}

7.4、结构体传参

struct point
{
	int arr[1000];
	int a;
};

struct point s = { {1,2,3,4},50 };

print1(struct point s)//结构体传参
{
	printf("%d\n", s.a);
}

print2(struct point* ps)//结构体地址传参
{
	printf("%d\n", ps->a);
}

int main()
{
	print1(s);//传结构体
	print2(&s);//传地址
	return 0;
}

结构体传参的时候,要传结构体的地址。函数传参的时候,参数是需要压栈的。 如果传递一个结构体对象的时候,结构体过大,参数压栈 的的系统开销比较大,所以会导致性能的下降。

8、调试

8.1、debug与release的区别

        debug是调试版本,包含调试信息,不对代码进行优化。

        release是发布版本,会对代码进行优化,是程序的运行速度更快

8.2、调试的快捷键

        F5 启动调试

        F9 创建断点和取消断点

        F10 逐过程调试

        F11 逐语句调试,可以进入函数内部

        ctrl+F5 开始执行不调试

8.3、调试时会用到的监视窗口

        调试-窗口-监视,可以输入查看变量的值

        调试-窗口-内存,可以查看变量存放的地址

        调试-窗口-调用堆栈,可以查看函数的调用关系

        调试-窗口-反汇编,可以查看反汇编信息

        调试-窗口-寄存器,可以查看寄存器的使用信息

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值