C语言总结day05

day05

1、函数间可以相互调用,但是不能调用main函数,main函数是被操作系统调用的。
2、数组作为函数参数

  • 数组元素可以作函数参数。(值传递)注意:数组元素可以用作函数实参,不能用作形参。
    • 例如int max(int x,int y);声明;max(a,a[i]);调用。
  • 数组名作函数参数。(地址传递):用数组元素作实参时,向形参变量传递的是数组元素的值,而用数组名作函数实参时,向形参(数组名或指针变量)传递的是数组元素首元素的地址。
    • 例如:float average(float array[]);声明(声明或定义函数时,形参数组可以不指定大小,);float score[10];average(score);调用;数组名。
    • 多维数组名作函数参数:只能这样用int max(int a[][10]或inta[5][10])

3、局部变量和全局变量(也称为外部变量:故函数外部定义的变量)

  • 变量的动态存储方式和静态存储方式
    • 全局变量放在静态存储区,在程序执行中它们占据固定的存储单元。
    • 动态存储区存放以下的数据
      • 函数形式参数。在调用函数时给形参分配存储空间。
      • 函数中定义的没有用关键字static声明的变量,即自动变量。
      • 函数调用时的现场保护和返回地址等。
    • 局部变量的存储类别
      • 自动变量(auto变量):函数中的形参和在函数中定义的局部变量(包括符合语句中定义的局部变量),都属于此类。
        • 注意:关键字"auto"可以省略,不写auto则隐含指定为"自动存储类别";如int b,c=3;和auto int b,c=3;是等价的。
      • 静态局部变量(static局部变量)satic int a=3;
        • 静态局部变量是在编译时赋初值的,即只赋初值一次,若未指定初值的话,C编译系统会自动给它赋初值0。而对自动变量赋初值,不是在编译时进行的,而是在函数调用时进行的,每调用一次函数重新给一个初值,相当于执行一次赋值语句。
    • 全局变量的存储类别
      • static全局变量
        • 将外部变量的作用域限制在本文件中。
      • extern全局变量,用extern 声明外部变量的时候,可以省略类型(因为它不是定义变量).例如extern int a;可以写成extern a;
        • 在一个文件内扩展外部变量的作用域。
        • 将外部变量的作用域扩展到其他文件

4、内部函数和外部函数

  • 如果一个函数只能被本文件其他函数所调用,它称为内部函数。
    • static int fun(in a,int b)
  • 可以被其他文件所调用
    • extern int fun(int a,int b)
    • C语言规定,如果在定义函数时省略extern,则默认为外部函数。

5、指针

  • 简单说明

    • 直接访问
      • printf(“%d\n”,i);scanf(“%d”,&i);k=i+j;这几个语句中都是通过变量名来查找到存储单元的地址,从而对存储单元进行存取操作。(程序经过编译以后已经将变量名转换为变量的地址)这种直接按变量名进行的访问,称为"直接访问"方式。
    • 间接访问
      • i=3; i_pointer=&i;将i的地址放在i_pointer这个变量中。然后通过*i_pointer来取出其中的值。注:一个变量的地址称为该变量的"指针"。例如地址2000就是变量i的指针。如果有一个变量专门用来存放另一变量的地址(即指针),则称它为"指针变量",上述的i_poniter就是一个指针变量(指针变量的值是地址(即指针))。
    • 在C语言提供两种指针运算符
      • *: 取指针目标运算符
      • &:取地址运算符
  • 定义指针变量的一般形式为:

    • 类型名 * 指针变量名
    • 注意:在定义指针变量时必须指定基类型,因为想通过一个指针引用一个变量,只知道地址(如2000)时不够的,因为无法判断是从地址为2000的一个字节中取一个字符数据还是从2000~2001两个字节中取出short型数据。因此必须知道该数据的类型,才能按存储单元的长度以及数据的存储形式正确地取出该数据。
    • 重点区分:
      • 在编译器里定义一个指针变量,编译器会给这个指针变量分配一个空间,这个空间里存放的是一段内存的首地址,先解释一段内存,一段内存的大小是与你所定义的指针类型相关的,比如int,这段内存占四个字节(当然要看你的机器是多少位的了),则这段内存的首地址是第一个字节的地址,如char类型,占一个字节,这段内存的首地址就是这个字节的地址,还如结构体类型,此时内存大小要看该结构体的所有属性所占内存之和。现在解释这个空间,编译器给指针分配的空间大小是和CPU的寻址长度相关的,比如32位的CPU,它的寻址长度为32位,那么这个空间也就占四个字节,其实不管你定义什么样的指针类型,这个空间只是用来存地址,只占四个字节,而真正该空间所存的地址是哪一段内存的首地址才和所定义的指针类型相关。
      • 说到指针的大小很多人都会想到int型,char型,double型,然后觉得不同类型的指针所占内存大小不同,其实这是一种误区.因为指针其实就是一个无符号整形,一个整数而已,它的大小取决于你的系统是16 32 还是64位的 16/8=2byte 32/8=4byte 64/8=8byte .但是你会问为什么我的系统是64位的,但是我的指针却是32位的4字节指针.这个也很简单解释,因为我们是用编译器来写代码的,编译器已经默认我们的程序是在32位系统下运行,所以我们在编译器当中看到的指针都是占4个字节.有人又会问,为什么不用64位来编译呢?因为我们的程序要兼容32位的机器啊!你以为每个人都用64位的机器吗??讨论完指针大小问题,我们再讨论一下指针所指向的内存块所占内存大小.地球人 都知道char占一个字节,int占2个字节,double占4个字节,long double占8个字节(这是默认的32位编译环境下,在64位下翻倍就是了),所以一个char指针所占内存为4个字节(32位下),所指向的内存区域占1个字节.同理其它类型也是一样的。
    • 指针变量作函数的参数:作用是将一个变量的地址传送到另一个函数中。(C语言实参变量和形参变量之间的数据传递是单向的"值传递"方式。因此不能通过执行调用函数来改变实参指针变量的值,但是可以该变实参指针变量所指变量的值)。
    • 指针变量的一个优秀处:在函数调用只可以得到一个返回值(即函数值),而使用指针变量作参数,可以得到多个变化了的值。
  • 通过指针引用数组

    • int * p = &a[0]; //p的值是a[0]的地址 int *p =a;//p的值是数组a首元素(即a[0])的地址。
    • 两指针相减,如p1-p2(只有p1和p2都指向同一个数组中的元素时才有意义)
    • a[3]:注意:[]实际上是变址运算符,即将a[i]按a+i计算地址,然后找出此地址单元中的值。和*(a+i)计算方式一样。
    • 注意点:int a[10];int *p;for(p=a;a<(p+10);a++)这是错误的,因为a代表数组的首地址,是常量,不可变的。
    • 用数组名作函数参数时,如果形参数组中各元素的值发生变化,实参数组元素的值随之变化。因为,C编译都是将形参数组名作为指针变量来处理的。例如:fun(int arr[],int n);->fun(int *arr,int n);
  • 通过指针引用多维数组

    • int a[5][5]; 而a[0]此时代表的是一个数组名,即第一行的首地址。故a[0]+1代表1行2列的地址。而a[0]与*(a+0)等价。故a[0]+1可写成*(a+0)+1。这是一个地址。从中取出数据为*(*(a+0)+1)
    • 难点
      • 数组指针和指针数组
      • (数组指针:代表该指针指向数组)int (p)[5];(是一个行指针,p指向20个字节的指针。)结合int a[5]区分。注意这里的P两侧的括号不能缺少,如果写成*p[4],由于方括号[]运算符级别高,因此p先于[]结合。
      • (指针数组:代表该数组元素都是指针类型数据)int p[5];p由于[]的优先级比高,故p先于[5]结合,形成p[5]的形式,这显然是数组的形式。
  • 通过指针引用字符串

    • char *string = “I love China”;printf(“%s\n”,string);
    • 理解:在对字符指针变量string初始化,实际上是把字符串第一个元素的地址赋给指针变量string;在输出的时候,%s是字符串是所用的格式符。在输出项中给出字符指针变量名string,则系统会输出string所指向的字符串的第一个字符,然后自动使string加1,使之指向下一个字符。直到遇到"\0"为止。(注意在内存中,字符串的最后被自动加了一个’\0’)
  • 指向函数的指针。(在编译时,编译系统为函数代码分配一段存储空间,这段存储空间的起始地址(又称入口地址)称为这个函数的指针)

  • 用法:

    • int max(int a,int b);int (*p)(int a,int b);//定义指向函数的指针变量p p=max;//使p指向max函数 c=(*p)(a,b);//通过指针变量调用max函数
    • 注意:p两侧的括号不可省略。表示p先与结合,是指针变量,然后再与后面的()结合,()表示函数。即该指针变量不是指向一般的变量,而是指向函数。
  • 指向指针数据的指针(多重指针)

    • 概念:指向指针数据的指针变量,称为指向指针的指针。
    • char p;分析:p的前面有两个号,而且运算符的结合性是从右向左,因此P相当于*(p),显然p是指针变量的定义形式。可以分为两部分看,char * 和(*p),后面的(*p)表示p是指针变量,前面的char 表示p指向的是char型的数据。也就是说,P指向一个字符指针变量(这个字符指针变量指向一个字符型数据。)
    • 指针数组作main函数的形参
      • int main(int argc,char **argv[]) 其中argc和argv就是main函数的形参,它们是程序的"命令行参数"。argc(argument count的缩写,意思是参数个数),argv(argument vector缩写,意思是参数向量),它是一个*char指针数组,数组中每个元素(其值是指针)指向命令行的一个字符串。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值