欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C语言的一些知识点

程序员文章站 2022-04-15 19:25:25
注意: 中数组的输入一定要注意不用“,”,要用“ ”隔开输入的两个元素。 用指针时一定要注意指针指向的地址。 16位机器,int占2个字节,32位占4...

注意:

中数组的输入一定要注意不用“,”,要用“ ”隔开输入的两个元素。

用指针时一定要注意指针指向的地址。

16位机器,int占2个字节,32位占4个字节。

在windows 64位中,一个汉字占2个字节,一个英文字母占1个字节。

在不同的编译器中,int究竟是16位还是32位,由编译器设计者决定。

不同类型的数据在内存的存放方式和所占字节数不一样,具体:

整型数据占4个字节,字符型数据占1个字节。

定义全局变量const char a[100]={"abcdefg"};将生成大小为100个字节的只读数据区,并使用“abcdefg”初始化。如果定义为:const char a[ ]={"abcdefg"};则根据字符串长度生成8个字节的只读数据段(还有'\0')

--------------

变量

--------------

在以下情况需要指定static存储类别:

希望函数中的局部变量的值在函数调用结束后不消失而继续保留原值,即其占用的存储单元不释放,在下一次该函数调用时,该变量已经有值,就是上一次函数调用结束时的值。

--------------

数组

--------------

当用数组名做函数的参数时,如果形参数组中各元素的值发生变化,实参数组的值随之发生变化。

如果a[i]是一维数组,则a代表数组首元素的地址,a[i]代表a数组序号为i的元素的存储单元。但如果a[i]是二维数组,则a[i]是一维数组名,它只是一个地址,并不代表某一元素的值(如同一维数组名只是一个指针常量一样)。

在二维数组中,a和a+1是指向行的指针,在它们前面加一个*,就是*a和*(a+1),它们就成为指向列的指针,分别指向a数组0行0列的元素和1行0列的元素。反之,在指向列的指针前面加&,就成为指向行的指针。a[0]指向0行0列的指针,在它前面加一个&,得&a[0],由于a[0]与*(a+0)等价,因此&a[0]与&*a等价,也就是与a等价,它指向二维数组的0行。

二维数组中,&a[i]或a+i指向行,而a[i]或*(a+i)指向列。

对于二维数组名a和*a,二者的区别在于类型不同。从概念上说,a表示二维数组a的首地址,而*a表示二维数组a第一行a[0]的首地址。这样在使用的时候就有所区别。比如 对a的操作a[4]表示a的第四行首地址,而对*a的操作(*a)[4]则代表第一行的第4个元素,即a[0][4]。

int (*p)[4]是指向包含四个元素的一维数组的指针变量;int *p[4]是指针数组,指针数组的的元素只能存放地址,不能存放整数。

--------------

指针

--------------

指针就是地址,变量的指针就是变量的地址。

*p1(指向a的值)和*p2(指向b的值)互换,即是把a和b的值互换,p1依旧指向a地址,p2依旧指向b地址(可用于函数调用)

指针p1(指向地址a)和p2(指向地址b)互换,a和b的值没换,只是把p1指向了b地址,p2指向了a地址,(只是用于同一个函数中)

综上,指针互换有两种,一种可以将其对应的地址的数互换,另一种是改变对应地址的数据,而是将自己所指向的地址换了。

*temp是指针temp指向的地址里存储的值,若未给temp赋值,则temp里对应的值是不确定的(不可预见的),所以,对*temp赋值,就是对一个未知单元赋值。因此,不能有*temp=*p1,但是可以有temp=*p1。

为了使在函数中改变了的变量值能被主函数main所调用,在函数调用时不能把要改变的值作为参数使用,而是应该用指针变量作为函数参数,在函数执行过程中使指针变量对应的值发生变化,函数发生变化后,这些变化依旧保存下来了。

c语言中,实参变量和形参变量之间的数据传递是单向的“值传递”方式,用指针变量做函数参数时同样要遵循这一原则,不可能通过执行函数来改变实参指针变量的值,但是可以改变实参指针变量所指变量的值。

在函数调用中,一般的参数可以得到且只能得到一个函数值,而指针做参数则可以得到多个变化了的值。

引用数组元素时,指针法相对于下标法,可以使目标程序质量更高(占用内存小,运行速度快)。

指针也可以有下标,如若当前p指向a[3],则p[2]表示*(p+2),指向a[5]。

如果有一个实参数组,想要在函数中改变此数组的值,实参和形参的对应关系如下:

(1)形参和实参都用数组名

(2)实参用数组名,形参用指针变量

(3)实参和形参都用指针变量

(4)实参为指针变量,形参为数组名

int (*p)[4]表示p是指针变量,指向有4个元素的一维数组,数组元素为整形,也就是p所指的对象是有4个整形元素的数组,此时p只能指向一个包含4个元素的一维数组,p的值就是该一维数组的起始地址。

下面语句定义了一个指向函数的指针变量p:

int(*p)(int ,int)

指针变量名为p,它指向的函数参数为int型,该定义的函数有两个int型的参数。

返回指针值的函数:int *a(int x, int y)

指针数组:int *p[4];这里的p[4]显然是数组形式,它有4个元素,前面的“*”表示此数组是指针型的,每个数组元素都可以指向一个整形变量。指针数组比较适合用来指向若干个字符串,使字符串处理更加灵活,方便。

多重指针,即指向指针的指针:int **p;

-----------------

内存分配

-----------------

***内存动态分配***

1.malloc

void *malloc(unsigned int size);其作用是在内存的动态存储区中分配一个长度为size的连续空间,形参size的类型定为无符号整型,此函数的值(即返回值)是所分配区域的第一个字节的地址,是一个指针型函数,返回的指针指向该分配区域的开头位置。 如:malloc(100);表示开辟100字节的临时分配域,函数值为其第一个字节的地址。注意指针的基类型为void,即不指向任何类型的数据,只提供一个地址,如果此函数未能成功的执行(例如内存空间不足),则返回空指针(null)。

2.calloc

void *calloc(unsigned n, unsigned size);其作用是在内存的动态存储区中分配n个长度为size的连续空间,这个空间一般比较大,足够保存一个数组。用calloc函数可以为一维数组开辟动态存储空间,n为数组元素个数,每个数组长度为size,这就是动态数组。函数返回指向所分配域的起始位置的指针,如果分配不成功,返回null。如:p=calloc(50,4);表示开辟50×4个字节的临时分配域,把起始地址赋给指针变量p。

3,free

void free(void *p);其作用是释放指针变量p所指向的动态空间,使这部分空间能重新被其他变量使用,p应是最近一次调用calloc或malloc函数时得到的返回值。如:free(p);表示释放指针变量p所指向的已分配的动态空间,free函数无返回值。

4.realloc

void *realloc(void *p,unsigned int size);如果已经通过malloc或calloc函数获得了动态空间,想改变其大小,可以用realloc函数重新分配。用realloc函数将p所指向的动态空间的大小改变为size,p值不变,如果分配不成功,返回null。如:realloc(p,50);表示将p所指向的已分配的动态空间改为50字节。

以上4个函数的声明在stdlib.h头文件中,用到这些函数时,应当用# include指令把头文件包含到程序文件中。

************

补: 动态内存分配

************

malloc的参数就是需要分配的内存字节(字符)数。如果内存池中的可用内存可以满足这个需求,malloc所分配的是一块连续的内存。内存数量的方式不同。

malloc和calloc都是返回一个指向被分配的内存块起始位置的指针。

malloc和calloc的主要区别是后者在返回指向内存的指针前把内存初始化为0。较小区别是它们请求内存数量的方式不一样。

如果malloc和calloc的返回值为null ,这说明内存不够或无法分配。

传给free的指针必须是一个从malloc,calloc或realloc函数返回的指针,传给free函数一个指针,让它释放一块并非动态分配的内存可能导致程序立即终止或在晚些时候终止。试图释放一块动态分配内存的一部分也有可能引起类似的问题。因为释放一块内存的一部分是不允许的,动态分配的内存必须一整块内存一起释放。不要访问已经被free函数释放了的内存。但是,realloc可以缩小一块动态内存的分配,有效的释放它尾部的内存。

但动态分配的内存不再需要使用时,它应该被释放,这样它以后可以被重新分配使用。分配内存但在使用完毕后不释放将引起内存泄漏。

-------------------

结构体指针

-------------------

将一个结构体变量的值传递给另一函数有三种方法:

1.用结构体变量的成员做参数。

2.用结构体变量做实参。

3.用指向结构体变量(或数组元素)的指针做实参,将结构体变量(或数组元素)的地址传给形参。

结构体变量所占内存长度是各成员占的内存长度之和。

-------------------

共用体类型

-------------------

union:用同一段内存存放不同类型的变量。共用体和结构体定义相似,但它们的含义不同。结构体变量所占内存长度是各成员占的内存长度之和,每个成员分别占有其自己的内存单元;而共用体变量所占的内存长度等于最长的成员的长度。

工哦你共用体类型数据的特点:

1.同一个内存段可以用来存放几种不同类型的成员,但在每一个瞬时只能存放其中一个成员,而不是同时存放几个。

2.可以对共用体变量初始化,但初始化表中只能有一个常量。

3.共用体变量中起作用的成员是最后一次被赋值的成员,在对共用体变量中的一个成员赋值后,原有变量存储单元中的值就取代。

4.共用体变量的地址和它的各成员的地址都是同一地址。

5.不能对共用体变量名赋值,也不能企图引用变量名来得到一个地址。

6.以前的c规定不能把共用体变量作为函数参数,但可以使用指向共用体变量的指针做函数参数。

7.共用体类型可以出现在结构体类型定义中,也可以定义共用体数组。

共用体类型数据一般是用在数据处理中,对同一段空间安排不同的用途时。

-------------------

文件的输入与输出

-------------------

文件是指存储在外部介质上数据的集合。一批数据是以文件形式存放在外部介质上的,操作是以文件为单位对数据进行管理的。如果想找存放在外部介质上的数据,必须先按照文件名找到所指定的文件,然后再从该文件中读取数据。要向外部介质上存储数据也必须先建立一个文件(以文件名作为标志),才能向它输出数据。c的数据文件由一连串的字符组成,对文件的存取是以字符为单位。

所谓的“打开”文件是指为文件建立相应的信息区(用来存放有关文件的信息)和文件缓冲区(用来暂时存放输入输出数据)。所谓“关闭”是指撤销文件信息区和文件缓冲区。,使文件的指针变量不再指向该文件,显然就无法进行对文件的读写了。