对C语言的小总结

C语言已经学完一段时间了,所以抽段时间对于所学的知识进行一个总结。


C语言里有32个关键字。(c99)


想了解C语言我们首先要了解他的数据类型:

数据长度因所在编译器不同范围会有差异,我所写的都是在32位平台下的范围。

char-(-128~127)一个比特位(一个比特位为8位二进制小数,无特别声明的话第一位为符号位)

short-(-32768~32767)两个比特位

int-(-2147483648~2147483647)四个比特位

long-(-2147483648~2147483647)四个比特位,最低不得低于int

float-(3.4 x 10^(-38)~ 3.4 x 10^(+38))

double-(1.7 x 10^(-308)~ 1.7 x 10^(+308))


在我们对于C语言里数据类型有了基本了解后,就开始学习了一些基本的、简单的语句,比如输出hello world这种,比较简单,就不具体实现了。


接下来我们学习了C语言中比较常见的一种体系,循环:常见的循环有两种,while循环和for循环还有do、while循环。

for循环:

for (int i = 0; i < 10; i++)
	{
		printf("%d ", i);
	}
在这个循环里,括号最左侧为设定循环变量和循环变量赋值的作用,中间的i<10位判断条件,如果条件成立,则进入循环,最右侧是当一次循环结束后在执行的条件,花括号里时循环所执行的语句,每循环一次,就打印此次的i。

while循环:

while (i < 10)
	{
		printf("%d ", i);
		i++;
	}
这个循环,与上面for循环的作用是相同的,在括号里时循环条件,符合就进循环,花括号里为循环执行的语句。

do{}while()循环:

do {
		printf("%d ", i);
		i++;
	} while (i < 10);
这个循环稍有不同,do、while循环会先进行一次循环然后在看判断条件是否符合而决定是否继续循环,这就意味着不管条件是否符合,循环里的语句一定会执行一次。

而在循环中,也有一些特殊的语句会影响到循环的进行,比如continue和break还有goto。

continue的作用是结束本次循环,也就意味着不管在何时使用这个语句,本次循环都会被直接打断,进行下一次循环。

break的作用则是直接结束循环,意思就是整个循环在此结束,不在进行。

goto,goto语句是一个不建议使用的语句,它会不分情况的任意跳转,随意使用会导致代码顺序非常的乱

int i = 10;
	L:
	if (i <11)
	{
		printf("%d", i);
		i++;
		goto L;
	}
	getchar();
在这个代码中,当第一次循环进行中,遇到goto语句,它会跳转到已设定标志的L处,继续执行程序。

数组:

1.概念:同一种元素的集合。

2.分类:一维数组和多维数组。

一维数组的初始化:

int arr[3] = { 1,2,3 };
多维数组就先声明多个一维数组,然后将它们联合起来。
3.特性:数组在底层是一组连续的空间,可以随机访问。

int arr[3] = { 1,2,3 };

比如对于这个数组,就有多种访问方法:

第一种是直接访问,arr[下标]的方式,数组元素下标由0开始,下标数比元素数少1。比如我要访问第三个,代码写出来就是arr[2]。

4.用法:用来存储元素,赋值方法通过访问修改存储值。

数组直接作为参数会降级处理,一维数组传参,函数会以数组首元素的地址接收,二维数组传参则作为第一行元素的地址接收,以此类推。

5.函数存在越界访问的问题,这个问题与函数在栈上开辟空间有关。

因为数组是一段连续的空间,用指针访问也很方便。

int arr[3] = { 1,2,3 };
	int* p = arr;//*p = 1;
	int a = *(p + 1);//a = 2;(加上2就会指向第三个元素)
	*(p + 1) = 4;//数组中第二个元素就会变为4


函数:

1.概念:在程序语言中,我们可以将一段经常使用的代码封装起来,在需要的时候可以直接调用,比如我们可以封装一个简单的加法函数:

int Add(int right, int left)
{
	return right + left;
}
这就是一个简单的函数,第一行的第一个int为返回值类型,返回值类型可以有很多种,int,char,指针,引用······right和left为参数。

Add为函数名,当我们在程序中需要使用它时,比如我们需要1和2相加:

a = Add(1, 2)//在我们需要两个数字相加时就可以直接这样调用。
int a = 1;
	int b = 2;
	int c = Add(a, b);
在这段代码里我们将a和b作为参数传给了Add函数,函数原型为:

int Add(int right, int left)
{
	return right + left;
}
在这里right就是a的一份临时拷贝,也就意味着right仅仅是数值与a一致,在函数内部改变它并不会影响主函数里a的值,同理b也一样。
在我们传参数时,也可以利用指针或者引用传递过去,利用指针和引用传递过去的是地址的一份临时拷贝,也就是说通过引用和指针去改变就会影响到主函数里变量的值了。


如图示,栈是由高地址向地地址的方向生长的,而且栈有其栈顶和栈底,在x86系统的CPU中,寄存器ebp保存的是栈底地址,称为帧指针,

寄存器esp保存的是栈顶地址,称为栈指针。而且还应该明确一点,栈指针和帧指针一次只能存储一个地址,所以,任何时候,这一对指针指向的是同一个函数的栈帧结构。

并且ebp一般由系统改变它的值,而esp会随着数据的入栈和出栈而移动,也就是说esp始终指向栈顶。

程序具体过程另外写文章就将函数栈帧。



代码的过程大致为预处理-编译-汇编-链接-生成可执行文件

预处理:预处理阶段就是对伪指令(#开头的指令)和特殊符号进行处理,对代码进行初步的转换,产生新的源代码供应给编译器。


    宏常量:

                  #define a 10          //这样定义后,a就成为了一个数值为10的常量,不能再进行赋值,也不用再声明,可以直接使用。

    宏函数:

#define MAX(a,b) (a>b?a:b) 
//这样MAX就成为了一个判断大数的函数,在后面的代码中可以直接调用


指针:

指针可以说是C语言的精髓所在,它的存在使我们的代码得到了很大程度的简化。

1.概念:存放数据地址

2.类型:指针有多种类型,根据所存数据决定

指针—指针本身就是一个地址,它存放的是指向数据的地址,而它也有自己的地址。

int* p[10];//指针数组,数组每一个元素都是一个指针
	int(*p)[10];//数组指针,指向数组的指针
	int(*p)(int, int);//函数指针,指向函数的指针
	p = Add;
	int c = (*p)(1, 2);

自定义类型:

结构体—struct

定义:不同数据的集合,也就是说结构体可以存放多种类型的数据。

struct studen
{
	char name[20];
	int num;
	int tele;
};
这是我定义的一个简单的结构体,这里面就可以同时存放char类型和int类型的数据。

结构体存在内存对齐,这是为了方便访问其中的数据。

内存对齐规则:

原则1、数据成员对齐规则:结构(struct或联合union)的数据成员,第一个数据成员放在offset为0的地方,

以后每个数据成员存储的起始位置要从该成员大小的整数倍开始(比如int在32位机为4字节,则要从4的整数倍地址开始存储)。

原则2、结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储。

(struct a里存有struct b,b里有char,int,double等元素,那b应该从8的整数倍开始存储。)

原则3、收尾工作:结构体的总大小,也就是sizeof的结果,必须是其内部最大成员的整数倍,不足的要补齐。

结构体也有一种特殊的存在,长度可变,因为里面放置了柔性数组。

联合体—(union)

也可以存放不同类型的数据,与结构体不同的是,联合体内各种类型内存是共享的,也就是相互覆盖的。

枚举—(enum)

枚举内数据后一个比前一个大1,如果不特别定义,就从1开始递增。

大小端:

数据在不同编译器下存放的方式是不同,有大端存储和小端存储,决定数据存储的方向。

文件操作:

fopen(文件路径)

fclose()关闭文件

fread()读取文件

fwrite()书写文件

fgets()从文件获取一个字符串

fgetc()从文件获取一个字符

fputs()向文件写入一个字符串

fputc()向文件写入一个字符

动态内存管理:

//malloc  动态开辟内存空间
	//使用方法:
    int* p =(int*) malloc(sizeof(int) * 2);
在这里,*p就指向了一个两个int大小的空间。

//calloc  动态开辟内存空间
	//使用方法:
	int* p = (int*)calloc( 2,sizeof(int));
calloc与malloc功能相似,参数不同。
int* p = (int*)calloc( 2,sizeof(int));
	p = (int*)realloc((void*)p, sizeof(int) * 3);
realloc是在已开辟空间的基础上,改变空间的大小,第一个参数为目标空间,第二个参数为需要改变成的大小。









  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值