C语言——第六章

news/2024/6/1 21:56:35 标签: 语言, c, 存储, null, 编译器
cle class="baidu_pl">
cle_content" class="article_content clearfix">
content_views" class="htmledit_views">

一.

变量存储空间的分类顺序

先声明的变量后分配存储空间;撤销的顺序与之相反:先建立的后撤销。这种机制就称为栈机制࿰c;好像往一个只能允许进出一个盘子的桶里放盘子࿰c;先放进的后拿出。在Cclass="tags" href="/tags/YuYan.html" title=语言>语言程序中࿰c;局部变量就被分配在栈区࿰c;而且是以高端为栈底建立的。所以后建变量的地址较小。

每个变量只有一个地址࿰c;但占用的空间不同


二.

一个指针所指连变量的类型࿰c;称为该指针的基类型。


三.

指向void类型的指针void *p;这表示指针变量不指向某一确定类型的数据。它的作用仅仅是用来存放一个地址࿰c;而不能指向非void类型的变量。例如࿰c;下面的写法是错误的。

int *p1;

void *p2;

int i;

p2 = &i;

printf("%d", *p2);

如果确实需要将&i的值放在p2中࿰c;应先进行强制类型转换࿰c;使之成为(void *)类型࿰c;再将p2赋值给p1时࿰c;同样应进行强制类型转换。

p2 = (void *)&i;

p1 = (int *)p2;

printf("%d", *p1);

注意:执行p1=(int *)p2之后࿰c;p2本身的类型并未改变。只是在向p1赋值前先进行强制类型转换࿰c;生成一个(int *)类型的临时数据赋值给p1


四.

#include<stdio.h>

int main()

{

int a[5] = {1, 3, 5, 7, 9}, i, *p;

printf("下标法:");

for(i = 0; i < 5; ++i)

printf("%d,", a[i]);

printf("\n数组名法:");

for(i = 0; i < 5; ++i)

printf("%d,", *(a + i));

printf("\n指针变量法:");

for(p = a; p < a + 5; ++p)

printf("%d,", *p);

printf("\n");

return 0;

}

虽然上面三种方法都能输出同样的结果࿰c;但它们的执行效率是不同的。用下标法访问数组元素时࿰c;是把a[i]转换成*(a+i)进行计算的࿰c;即先计算出数组元素的地址(a+i)c;然后再找到它所指的存储单元࿰c;读出或写入它的值。而用指针变量p指向数组元素时则不必每次都计算数组元素地址。特别是使用p++这样的操作是速度比较快的。


五.

char str[M][N];

char *str[N];

char **str;

1.char str[M][N],在这个声明中࿰c;有两个相同的数组类型说明符[]c;按照从左到右的结核性࿰c;额可以首先确定str是一个大小为M的向量(一维数组)。对于数组࿰c;自然要说明其类型࿰c;由char[N]补充说明࿰c;这个数组是长度为N的字符数组类型࿰c;即它的每个元素都是长度为N的字符数组。用这种方式存储的几个字符串占有连续的存储空间。

2.char *str[N],在这个声明中࿰c;有两个不同的数组类型生命符[]*。其中数组类型生命符的优先级别高࿰c;可首先确定str是一个大小为N的一维数组。余下的char*补充说明:这个数组的每个元素都是字符类型指针。采用这种方式存储的几个字符串的长度可以不同࿰c;不一定占有连续的存储空间。

3.char **strc;在这个声明中࿰c;有两个相同的类型生命符*。按照自右向左的结合性࿰c;可以首先将后面的一个*与名字相结合࿰c;得出结论:str是一个指针。对于指针࿰c;就要声明它指向什么。由余下的char*补充声明࿰c;这个指针是指向字符指针的。

用二维字符数组存储c;需要按照最长字符串开辟存储空间࿰c;而用字符串数组(即字符指针数组)存储时࿰c;可以为不同长度的字符串开辟不同长度的存储空间。采用字符串数组来存储字符串不进可以节省空间࿰c;还可以提高执行效率。例如࿰c;对存储的字符串进行交换࿰c;如果是二维数组存储c;必须实际交换所存储的字符串࿰c;而采用字符指针数组则只需要交换两指针变量的值࿰c;不需要实际移动字符串。


六.P212

全局变量是在编译时在内存静态存储区分配的࿰c;非静态的局部变量是程序运行是在栈区自动分配的࿰c;而为指针所进行的内存空间动态分配是在程序运行过程中在自由内存区——堆(heap)区分配的。堆可以形成比较大的存储空间࿰c;供动态分配使用。

动态分配的特点是࿰c;可以由程序员控制࿰c;在需要时分配࿰c;在不需要时释放࿰c;还可以根据具体需要改变所分配存储空间的大小。

以下四个函数包含在stdlib.h中。

1malloc函数࿰c;其函数原型为:

void * malloc(unsigned int size)

其作用是在内存的动态存储区中分配一个长度为size的连续空间࿰c;函数的返回值是所分配区域的第一个字节的地址。

2calloc函数࿰c;其函数原型为:

void * calloc(unsigned n,unsigned size)

其作用是在内存的动态存储区中分配n个长度为size的连续空间࿰c;一般用来保存一个数组(n为数组元素的个数࿰c;每个数组元素长度为sizec;这就是动态数组)࿰c;函数返回指向所分配域的起始位置的指针。如果分配不成功࿰c;返回NULL

3free函数࿰c;其原型为:

void free(void * pointer)

其作用是释放指针变量p所指向的动态空间࿰c;使这部分空间能重新被其他变量使用。pointer应是最近一次调用callocmalloc函数所得到的函数返回值。free函数没有返回值。

4realloc函数࿰c;其原型为:

void * realloc(void * pointer,unsigned int size)

对已使用malloc函数或calloc函数获得的动态空间进行重新分配。如果重新分配不成功࿰c;返回NULL

说明:

1.因为void *p说明pvoid*类型的指针࿰c;声明其类型是未确定的类型࿰c;可以通过强制转换的方法将其转换为任何其他类型。例如

double *pd=NULL;

pd = (double *)calloc(10,sizeof(double));

并且通过(double*)calloc()的返回类型进行强制类型转换࿰c;以便把double类型数据的地址赋值给指针pd 

2.使用sizeof的母的是用来计算一种类型所占有的字节数࿰c;以便适合不同的编译器

3.由于动态分配不一定成功࿰c;为此要附加一段异常处理程序࿰c;不致程序运行停止

if(p == NULL)

{

printf("No enough memory!\n");

exit(1);

}


七.

其实main函数也可以有参数。有参数的main函数的原型为

 int main(int argcchar *argv[]);

也就是说࿰c;带参数main函数的第一个形参argc是一个整型变量࿰c;第二个形参argv是一个指针数组࿰c;其每个元素都指向字符型数据(即一个字符串)。

这两个参数的值从哪里传递而来呢?main函数是主函数࿰c;它不能被程序中的其他函数调用࿰c;因此显然不可能从其他函数向它传递所需要的参数值࿰c;只能从程序以外传递而来。也就是在启动一个程序时࿰c;从程序的命令行中给出。


八.

main()

{

int a[5];

int i;

for(i = 0; i < 5; ++i, ++a)

printf("%d", *a);

}

这段程序看起来没错࿰c;但是仔细一看࿰c;或者一运行就会发现有错误。因为a++的使用而导致了这种情况的发生。因为a代表数组的起始地址࿰c;是一个常量。而常量是不能进行自加运算的。所以a++是错误的。如果a只是一个函数里面的形参࿰c;那么就可以作为一个指针变量就可以进行自加运算了。


九.

利用指针实现各种函数࿰c;如:strcpy, strlen, stringcat, stringchr, delchar等。。


十.

一个函数包括一系列指令࿰c;在内存中占据一片存储单元࿰c;它有一个起始地址࿰c;即函数的入口地址࿰c;通过这个地址可以找到该函数。也可以定义一个指针变量࿰c;使它的值等于函数的入口地址࿰c;通过这个指针变量也能调用此函数࿰c;这个指针变量称为指向函数的指针变量。例如:

int (*p)();表示p指向一个“返回正兴致的函数”。注意*p两侧的括号不能省略࿰c;如果写成“int *p()”就变成“返回指针值的函数”了。

可以用指向函数的指针变量作为被调用函数的实参。由于该指针变量是指向某一函数的࿰c;因此先后使指针变量指向不同的函数࿰c;就可以在被调函数中调用不同的函数。


十一.

有人可能会认为࿰c;实现不同的功能时直接调用不同的函数即可࿰c;例如在main函数中直接调用几个函数即可࿰c;何必通过一个函数借助传递函数地址的方式实现呢?的确࿰c;如果程序功能很简单࿰c;可以不通过这种方法。但是在一些较为复杂的问题中࿰c;以函数地址作为参数的优越性就比较明显了。。。比如求一个函数的定积分。显然࿰c;如果不采用这种方法࿰c;而分别编写求解某函数定积分的函数࿰c;将是十分麻烦的。

cle>

http://www.niftyadmin.cn/n/1516709.html

相关文章

CentOS 7 升级 kernel,给kernel打patch

CentOS 7 rpm安装或升级最新的内核&#xff1a;https://linux.cn/article-8310-1.html ELRepo&#xff0c;an RPM repository for Enterprise Linux packages&#xff1a;http://www.elrepo.org Linux Kernel Archives&#xff0c;可下载kernel源码&#xff1a;https://www.ke…

C语言——第七章

一&#xff0e; 在计算机中&#xff0c;位(bit)是表示和存储信息的最小单位&#xff0c;1B8bit。C语言提供一种在位一级进行操作的机制。它允许在一个结构体中以位为单位来指定其成员所占内存的长度&#xff0c;这种以位为单位的成员称为“位段”&#xff0c;或“位域”。例如&…

深入浅出Wince的存储

刚学wince那会&#xff0c;对wince下面的文件存储老是理解不了&#xff0c;或者说容易搞混. 最近公司在做一个wince下的终端移植项目&#xff0c;中间也 遇到了一些存储方面的问题&#xff0c;我自己学wince也有一段时间了&#xff0c;现在对wince的几个存储的概念也可以谈论一…

一元多项式的乘法与加法运算_多项式的矩阵表示及乘法运算

一元多项式的乘法将多项式表示为向量、矩阵&#xff0c;并不是很有新意的想法&#xff0c;我们主要想研究的是将两多项式 、 乘法运算转化为矩阵运算。先举个例子——例 1我们将多项式以降幂方式排列&#xff0c;然后用各次幂项的系数做成向量。显然&#xff0c;这样的表示是一…

WINCE注册表的存储和加载

先说原理:注册表类型分为基于对象存储的注册表和基于HIVE的注册表&#xff0c;在定制内核的时候只能选择其中一种。从理论上讲这两种注册表都能够实现永久保存注册表数据&#xff0c;但是采用不同的类型会影响CE的启动顺序和启动速度&#xff0c;还会影响内存的使用量。我还是趋…

C语言——第八章

这一章没有怎么仔细看&#xff0c;其实也很简单&#xff0c;记住格式就行了。等不会的时候可以翻书看一下就OK了。 到此为止&#xff0c;谭浩强的这本书已经看完一遍了&#xff0c;找到了10个左右的错误&#xff0c;感觉有点惊讶。后天C语言的圣经就买回来了&#xff0c;到时候…

es数据迁移_Elasticsearch数据备份说明

假设ES集群有三个节点:192.168.1.10192.168.1.11192.168.1.121. 创建共享目录在三个节点上创建共享目录/mnt/backup/&#xff0c;使三个节点的es用户都可以读写该目录。&#xff08;推荐使用nfs创建共享目录&#xff09;2. 修改ES配置在elasticsearch.yml中加入一行:path.repo:…

POJ-1753 Flip Game【枚举+BFS+位存储】

题目链接&#xff1a;http://poj.org/problem?id1753 题目大意&#xff1a;给你一个4x4的方格&#xff0c;里面放了16枚棋子&#xff0c;每个棋子有2面:黑或白。现在给出它们的初始状态&#xff0c;每次你可以翻转一个棋子&#xff0c;但是规定必须把它周围四个方向的同时翻转…