尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

【c语言】1.3 c语言的灵魂-指针

【c语言】1.3 c语言的灵魂-指针 概述1.指针的出现是为了实现间接访问。在汇编中都有间接访问其实就是CPU的寻址方式中的间接寻址。2.变量的本质就是一个地址具体数值和变量名绑定变量类型决定这个地址的延续长度也决定了这个数在内存中怎么存储的问题3.数组名是数组第一个元素的地址。4.数组下标方式和指针方式均可以访问数组元素两者的实质其实是一样的。在编译器内部都是用指针方式来访问数组元素的数组下标方式只是编译器提供给编程者一种壳语法糖而已。所以用指针方式来访问数组才是本质的做法。5.int和float的解析方式是不兼容的所以int *转成float *再去访问绝对会出错。6.数组作为函数形参时[]里的数字是可有可无的。为什么因为数组名做形参传递的实际只是个指针根本没有数组长度这个信息。7.这个世界上根本没有传值和传址这两种方式C语言本身函数调用时一直是传值的只不过传的值可以是变量名也可以是变量的指针。8.char str[] hello ; sizeof (str) 6 ;9.strlen() 接收的参数只能是字符串10.得到元素数组个数sizeof(a) /sizeof(a[0])内存三种内存来源栈stack、堆heap、数据区.data 一个(代码区(1)在一个C语言程序中能够获取的内存就是三种情况栈stack、堆heap、数据区.data(还有一个代码区栈内存 注意临时性函数不能返回栈变量的指针因为这个空间是临时的堆内存 注意临时性堆内存只在malloc和free之间属于我这个进程而可以访问。在malloc之前和free之后数据区.data:数据区是用于存储全局变量和静态变量的一种内存区域。全局变量和静态变量在程序运行期间一直存在它们的内存分配在程序启动时完成并在程序结束时释放。程序中内存从哪里来代码段、数据段、bss段编译器在编译程序的时候将程序中的所有的元素分成了一些组成部分各部分构成一个段所以说段是可执行程序的组成部分。(1)代码段代码段就是程序中的可执行部分直观理解代码段就是函数堆叠组成的。(2)数据段也被称为数据区、静态数据区、静态区数据段就是程序中的数据直观理解就是C语言程序中的全局变量。注意全局变量才算是程序的数据局部变量不算程序的数据只能算是函数的数据 放在.data段的变量有2种第一种是显式初始化为非零的全局变量。第二种是静态局部变量也就是static修饰的局部变量。普通局部变量分配在栈上(3)bss段又叫ZI(zero initial)段、通常是指用来存放程序中未初始化的或者显式初始化为0的全局变量一块内存区注意区分数据段.data和bss段的区别和联系二者本来没有本质区别都是用来存放C程序中的全局变量的。区别在于把显示初始化为非零的全局变量存在.data段中而把显式初始化为0或者并未显式初始化C语言规定未显式初始化的全局变量值默认为0的全局变量存在bss段 bss段和.data段并没有本质区别几乎可以不用明确去区分这两种注意数据区中的常量区存放常量、const修饰的变量、字符串常量。(1)C语言中使用char *p linux;定义字符串这个linux字符串实际上是一个常量字符串而不是变量字符串。(2)const型常量C语言中const关键字用来定义常量常量就是不能被改变的量。const的实现方法至少有2种第一种就是编译将const修饰的变量放在代码段去以实现不能修改普遍见于各种单片机的编译器第二种就是由编译器来检查以确保const型的常量不会被修改实际上const型的常量还是和普通变量一样放在数据段的gcc中就是这样实现的。总结1.函数内部临时使用出了函数不会用到就定义局部变量。2.堆内存和数据段几乎拥有完全相同的属性大部分时候是可以完全替换的。但是生命周期不一。3.堆内存的生命周期是从malloc开始到free结束而全局变量是从整个程序一开始执行就开始。野指针指向地址是不可预知的所以有3种情况第一种是指向不可访问操作系统不允许访问的敏感地址譬如内核空间的地址结果是触发段错误这种算是最好的情况了第二种是指向一个可用的、而且没什么特别意义的空间譬如我们曾经使用过但是已经不用的栈空间或堆空间第三种情况就是指向了一个可用的空间而且这个空间其实在程序中正在被使用譬如说是程序的一个变量x那么野指针的解引用就会刚好修改这个变量x的值导致这个变量莫名其妙的被改变程序出现离奇的错误。一般最终都会导致程序崩溃或者数据被损害。这种危害是最大的。NULL 本质是0#ifdef _cplusplus // 定义这个符号就表示当前是C环境#define NULL 0 // 在C中NULL就是0#else#define NULL (void *)0 // 在C中NULL是强制类型转换为void *的0#endif在C语言中int *p; 你可以p (int *)0但是不可以p 0;因为类型不相同。所以NULL的实质其实就是00地址处作为一个特殊地址0地址在一般的操作系统中都是不可被访问的函数需要向外部返回多个值时怎么办(1)一般来说函数的输入部分就是函数参数输出部分就是返回值。问题是函数的参数可以有很多个而返回值只能有1个。这就造成我们无法让一个函数返回多个值。(2)现实编程中一个函数需要返回多个值是非常普遍的因此完全依赖于返回值是不靠谱的通常的做法是用参数来做返回在典型的linux风格函数中返回值是不用来返回结果的而是用来返回0或者负数用来表示程序执行结果是对还是错是成功还是失败。(3)普遍做法编程中函数的输入和输出都是靠函数参数的返回值只是用来表示函数执行的结果是对成功还是错失败。如果这个参数是用来做输入的就叫输入型参数如果这个参数的目的是用来做输出的就叫输出型参数。(4)输出型参数就是用来让函数内部把数据输出到函数外部的。例子main函数int a, b 0, ret -1; a 30; ret multip5_3(a, b); if (ret -1) { printf(出错了\n); } else { printf(result %d.\n, b); } int multip5_3(int a, int *p) { int tmp; tmp 5 * a; if (tmp 100) { return -1; } else { *p tmp; return 0; } }
返回列表