(三)C语言基础(数组,内存分配,函数指针)

六 数组

1. 数组基础

  • 取数组地址:&cArray,与cArray相同,其为数组第一个元素地址
  • 取数组对应索引元素的值:cArray[0] 或 *(cArray+0)(注意与 “*cArray+0” 的区别)
  • 取数组对应索引元素地址:&cArray[0] 或 cArray+0
#include<stdio.h>
#include<stdlib.h>

/*
数组:
1.数组的取值
2.数组的取地址(数组地址与元素地址)
3.数组是一块连续的内存空间
4.数组的设计 
*/ 

main(){
    char cArray[] = {'H','E','L','L','O'}; 
    int  iArray[] = {2,0,1,6,5};

    //取数组的值
    printf("cArray[0] = %c\n",cArray[0]); //cArray[0] = H
    printf("iArray[0] = %d\n",iArray[0]); //iArray[0] = 1

    //1.取地址 
    printf("&cArray    = %#x\n",&cArray);//&cArray = 0x9ffe40 ,数组地址为首元素地址 
    //数组是一块连续的内存空间 
    printf("&cArray[0] = %#x\n",&cArray[0]);//&cArray[0] = 0x9ffe40,一个字母为1字节 
    printf("&cArray[1] = %#x\n",&cArray[1]);//&cArray[1] = 0x9ffe41
    printf("&cArray[2] = %#x\n",&cArray[2]);//&cArray[2] = 0x9ffe42
    printf("&cArray[3] = %#x\n",&cArray[3]);//&cArray[3] = 0x9ffe43

    printf("cArray+0地址 = %#x\n",cArray+0); //cArray+0地址 = 0x9ffe40
    printf("cArray+1地址 = %#x\n",cArray+1); //cArray+1地址 = 0x9ffe41
    printf("cArray+2地址 = %#x\n",cArray+2); //cArray+2地址 = 0x9ffe42
    printf("cArray+3地址 = %#x\n",cArray+3); //cArray+3地址 = 0x9ffe43

    printf("&iArray    = %#x\n",&iArray);//&iArray[0] = 0x9ffe20
    printf("&iArray[0] = %#x\n",&iArray[0]);//&iArray[0] = 0x9ffe20,一个int4字节 
    printf("&iArray[1] = %#x\n",&iArray[1]);//&iArray[1] = 0x9ffe24
    printf("&iArray[2] = %#x\n",&iArray[2]);//&iArray[2] = 0x9ffe28
    printf("&iArray[3] = %#x\n",&iArray[3]);//&iArray[3] = 0x9ffe2c

    //2.取值
    //此种取法为取下一个字母(ASCII码?)
    printf("cArray = %c\n",*cArray);     //cArray = H
    printf("cArray[0] = %c\n",*cArray+0);//cArray[0] = H
    printf("cArray[1] = %c\n",*cArray+1);//cArray[1] = I
    printf("cArray[2] = %c\n",*cArray+2);//cArray[2] = J
    printf("cArray[3] = %c\n",*cArray+3);//cArray[3] = K
    //此种取法为向下一个元素移动
    printf("cArray[0] = %c\n",*(cArray+0));//cArray[0] = H 
    printf("cArray[1] = %c\n",*(cArray+1));//cArray[1] = E
    printf("cArray[2] = %c\n",*(cArray+2));//cArray[2] = L
    printf("cArray[3] = %c\n",*(cArray+3));//cArray[3] = L

    printf("iArray = %d\n",*iArray);     //iArray = 2
    printf("iArray[0] = %d\n",*iArray+0);//iArray[0] = 2
    printf("iArray[1] = %d\n",*iArray+1);//iArray[1] = 3
    printf("iArray[2] = %d\n",*iArray+2);//iArray[2] = 4
    printf("iArray[3] = %d\n",*iArray+3);//iArray[3] = 5

    printf("iArray[0] = %d\n",*(iArray+0));//iArray[0] = 2
    printf("iArray[1] = %d\n",*(iArray+1));//iArray[1] = 0
    printf("iArray[2] = %d\n",*(iArray+2));//iArray[2] = 1
    printf("iArray[3] = %d\n",*(iArray+3));//iArray[3] = 6

    system("pause");
} 

2.1 例子 - 输入数组

#include<stdio.h>
#include<stdlib.h>

main(){
    //1.用户输入数组长度
    printf("请输入数组的长度:\n");
    int length;
    scanf("%d",&length);
    printf("输入的长度为:%d\n",length);
    //2.根据长度创建数组
    int aArray[length];
    //3.用户输入数组的值
    int i;
    for(i=0;i<length;i++){
        printf("请输入第%d个值:\n",i+1);
        scanf("%d",&aArray[i]);
    }
    //4.把数组内容打印出来   
    for(i=0;i<length;i++){
        printf("输出第%d个值:%d\n",i+1,aArray[i]);
    }
    system("pause");
} 

2.2 例子 - 指针的长度

#include<stdio.h>
#include<stdlib.h>

main(){
    int* iPoint;
    char* cPoint; 

    printf("iPoint的长度 = %d\n",sizeof(iPoint));//4
    printf("cPoint的长度 = %d\n",sizeof(cPoint));//4
    system("pause");
} 

3. 动态数组

  • realloc函数
  • malloc函数
#include<stdio.h>
#include<stdlib.h>

/*
动态创建数组步骤:
1.获取一个长度 
2.根据长度分配内存空间
3.数组元素依次赋值
4.接收扩展长度
5.根据长度重新分配内存空间
6.扩展的长度赋值
7.输出数组 

结果: 
请输入创建数组的长度:
3
输入数组的长度为:3
请输入第1个元素的值:
3
请输入第2个元素的值:
4
请输入第3个元素的值:
5
请输入扩展数组的长度:
2
扩展数组的长度为:2
请输入第4个元素的值:
6
请输入第5个元素的值:
71个元素的值为:32个元素的值为:43个元素的值为:54个元素的值为:65个元素的值为:7
*/ 
main(){
    printf("请输入创建数组的长度:\n") ;
    //1获取一个长度 
    int length;
    scanf("%d",&length);
    printf("输入数组的长度为:%d\n",length) ;
    //2据长度分配内存空间
    int* iArray = malloc(length*4);
    //3组元素依次赋值
    int i;
    for(i=0;i<length;i++){
        printf("请输入第%d个元素的值:\n",i+1);
        scanf("%d",iArray+i);
    }
    //4接收扩展长度
    int length1; 
    printf("请输入扩展数组的长度:\n") ;
    scanf("%d",&length1);
    printf("扩展数组的长度为:%d\n",length1) ;
    //5根据长度重新分配内存空间
    iArray = realloc(iArray,(length+length1)*4);
    //6根据长度重新分配内存空间
    for(i=length;i<length+length1;i++){
        printf("请输入第%d个元素的值:\n",i+1);
        scanf("%d",iArray+i);
    } 
    //7输出数组
    for(i=0;i<length+length1;i++){
        printf("第%d个元素的值为:%d\n",i+1,*(iArray+i));
    }
    system("pause");
} 

七、内存分配

变量的分配
  • 从静态存储区域分配
    内存在程序编译的时候已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static变量
  • 从栈上创建
    执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动释放。栈内存分配效率高,但容量有限
  • 从堆上分配
    动态内存分配。程序在运行的湿乎乎用malloc或new申请内存,自己负责free或delete释放内存,使用灵活,但是容易造成问题。
堆和栈的区别
  1. 申请方式
    • 栈:有系统自动分配,如声明一个局部变量int b,在调用函数时需要保持变量,如递归调用,要系统自动分配一个栈空间,后进先出。
    • 堆:需要自己申请,并指明大小
  2. 申请后的系统响应
    • 栈:只要神域空间大于所申请的空间,系统将为程序提供,否则报异常提示栈溢出。
    • 堆:首选应该知道操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时,会遍历该链表,
      寻找第一个空间大于申请空间的堆节点,然后将该节点从空闲节点链表中删除,并将该节点的空间分配给程序。
      另外,对于大多数系统,会在这块内存空间中的首地址记录本次分配的大小,这样,代码中的delete语句才能正确释放本内存空间。
      另外,由于找到的堆节点大小不一定正好等于申请的大小,系统会自动将多余的那部分重新放入空闲链表中。
  3. 申请大小的限制
    • 栈:在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存区域。意思是栈顶的地址和栈的最大容量是系统预先规定好的。在WINDOWS下,栈的大小默认是2M。
    • 堆:堆是向搞地质扩展的数据结构,是不连续的内存区域,空间比较灵活,也比较大。
  4. 申请效率
    • 栈:系统自动分配,速度较快,单程序员无法控制。
    • 堆:malloc/new分配的内存,一般速度比较慢,而且容易产生内存碎片,但是用起来方便。
  5. 存储内容
    • 栈:在函数调用时,第一进栈的是主函数后的下一条指令的地址,然后是函数的个个参数,在大多数c编译器中,参数是由右往左入栈的,然后是函数的局部变量。注意静态变量不入栈。
    • 堆:一般在堆的头部用一个字节存放堆的大小。堆中的具体内容有程序员安排。
  6. 内存回收
    • 栈:编译器自动回收
    • 堆:free显式回收

1. 静态内存分配

1.1 说明
  • 静态内存是栈分配的
1.2 实例
#include<stdio.h>
#include<stdlib.h>

/*
静态内存分配 :
静态内存是程序编译执行后系统自动分配,由系统自动释放 
*/

void func(int** address){ 
    int i=100;
    //把i对应的地址赋值给iPoint 
    *address = &i;
} 

main(){
    int* iPoint;

    func(&iPoint);//一级指针的地址为二级指针 

    //注意到i为定义到func函数中的变量 
    printf("*iPoint = %d\n",*iPoint); //*iPoint = 100
    //执行完成后栈中func部分被销毁,i不存在,iPoint无法指向 
    printf("*iPoint = %d\n",*iPoint); //*iPoint = 0
    printf("*iPoint = %d\n",*iPoint); //*iPoint = 0

    system("pause");    
} 

2. 动态内存分配

2.1 说明
  • malloc()//分配
  • ralloc()//重新分配,使用见动态数组
  • free()//释放
2.2 实例
#include<stdio.h>
#include<stdlib.h>

/*
动态内存分配 
*/
void func(int** address){
    int i = 100;
    int* temp;

    //malloc(int),返回内存地址
    //这个内存地址,存放在堆空间,不会被系统自动回收 ,其中保存的值自然不会 
    temp = malloc(sizeof(int));
    //将地址赋值 
    *temp = i;
    //将地址赋给二级指针的值 
    *address = temp;

    //回收堆空间变量 
    //free(temp);   
}

main(){
        int* iPoint;

    func(&iPoint);//一级指针的地址为二级指针 

    //注意到i为定义到func函数中的变量 
    printf("*iPoint = %d\n",*iPoint); //*iPoint = 100
    printf("*iPoint = %d\n",*iPoint); //*iPoint = 100
    printf("*iPoint = %d\n",*iPoint); //*iPoint = 100

    system("pause");
} 

八、函数指针

1. 说明

  • 定义一个带参数和返回值的函数指针,指向一个函数

2.实例

#include<stdio.h>
#include<stdlib.h>

/**
函数指针 
*/


//定义一个函数
//1. 指针参数等于函数参数的情况:
Log: result = 20

int add( x,int y){
    return x + y;
} 


/*
2. 指针参数多于函数参数的情况:
只有函数参数个数对应的参数能传递过来 
Log:result = 12 

int add(int x){
    return x;
} 
*/


/*
3. 指针参数少于函数参数个数的情况:
函数参数的前指针参数个赋值正确,后面参数被赋为内存垃圾值 
Log: z = 6233040 result = 6233065 

int add(int x,int y,int z){
    printf("z = %d ",z);
    return x + y + z;
}
*/

int main(void){
    //定义函数指针
    //定义一个两参的函数指针 
    int (*quantai)(int x,int y); 
    //函数指针赋值
    //指针指向函数名 
    quantai = add;
    //使用函数指针 
    int result = quantai(12,13);
    printf("result = %d",result);
    return 0;
} 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值