10.C语言指针3

==============

指针

==============

指针

        1.掌握的复合类型
            1》元素是指针的数组
            2》指向数组的指针
            3》指向指针的指针
        2.二维数组传参
        3.了解的复合类型
            1》返回值为指针的函数
            2》指向函数的指针
        4.内存的管理方式
            1》内存的划分
            2》各区的作用
        5.动态内存的分配
            1》malloc函数的使用
            2》free的函数
        6.常用内存管理函数
            1》memset函数的使用

一、掌握的复合类型

int * p[10];//方法:看标识符离谁最近,就是谁
//这是一个数组,10个元素,每个元素是指针。
//元素是指针的数组。
// 有十个指针,可以存放10个整型变量的地址

//p离中括号近,p是一个数组,元素是指针

int a,b,c,d;
int * p[10];
printf(“%ld %ld\n”,sizeof(p),sizeof(int *[10]));
printf(“%ld %ld\n”,sizeof(p[0]),sizeof(int *));

//p:80个字节   int*【10】80个字节
//  p【0】8个字节     int *  8个字节
p[0]=&a;  
p[1]=&b;
p[2]=&c;
p[3]=&d;

*p[0]=-78;
printf(“%d\n”,a);
int (*p)[10];//指向数组的指针、p的指针、二维数组传参;
//这是一个指针,指向数组的指针。
//p离*最近,p是一个指针,指向数组。
int a[10]={1,2,3};
int (*p)[10]=&a;  //指向整个数组a
int *q=a;    //指向a[0]

//数组的地址&a,是数组第一个字节的地址。
//a[0]的地址a,是a[0]第一个字节的地址。
//因此,&a和a的值大小相等,但是类型不同。

//假设数组的地址是0x101
//q找到地址为0x101的字节,取4字节得到a[0]
//
p找到地址为0x101的字节,取40个字节,得到整个数组。

//q+1加4
//p+1加40

printf(“%ld %ld\n”,sizeof(p),sizeof(int(*)[10]);
printf(“%ld %ld\n”,sizeof(*p),sizeof(int [10]););

p 有8个字节 int(*)[10] 表示的是80个字节;
p 40个字节(p表示数组) int【10】表示的是数组;有40个字节

int * * p;
//这是一个指针,指向整型指针。
//指向指针的指针,二级指针。
//装指针的地址。
//传一个变量地址,可以改变一个变量的值,传指针的地址,改变指针的值,修改指针的指向。

int a;
int *p=&a;
changePointer(&p);

//  a=2;
q==&a;
*q==a;
*q==a==2;

p=&q//p指向了指针;
*p=&b;//p==&q;*p==q;   q==&a;因为q==&b;*p=&b;   

void changePointer(int * * q)  //q=&p;
{
  *q=NULL;
}

练习:

1》int (*p)[10];
    int **q;
    int * x[10];
    p++;  是加多少?
    q++; 是加多少?
    x++;  是加多少?

二、二维数组传参

int a[5][6]={};
func(a);     //传&a[0]



void func(int (*p)[6] )
{
    p[1][2]=5;          //a[1][2]
    //p[1]是跳过24个字节
}

原则:数组名就是数组的首元素地址。

三、了解的复合类型

int * p(int);
//这是一个函数,参数是一个int,返回值是指针(地址)。

int (*p)(int);
//这是一个指针,指向函数
//函数指针

int (*p)(int,int)=add;  //初始化
//这是函数指针,指向add这个函数
p=add;   //给p赋值

printf(“%d\n”,p(3,4));
//当一个函数指针指向一个函数,调用指针如同调用函数。


//函数名可以赋值给一个指针,说明函数名是一个地址。
//函数名是函数的入口地址。


int add(int a,int b)
{
    return a+b;
}

四、内存的管理方式

1、内存的划分与作用
1》栈区——系统分配以及回收内存。函数体内创建的变量分配在栈区。
2》堆区(动态内存分配)——由用户(程序员)分配和回收,如果程序员未回收内存,那么,内存就会越用越少,有可能导致内存不够用,程序崩溃。如果没有达到不够用,程序安然无恙。当程序退出时,堆内存由系统回收。
3》常量区——用于存入常量的内存区域。
4》静态区(全局区)——定义在函数体外面的变量,由系统开辟空间,程序运行过程中一直存在,直到程序退出,由系统回收。
5》代码区——存放源代码编译结果的区域。

五、动态内存的分配

1、malloc函数的使用及free的函数
void * malloc(unsigned int size);
malloc函数向系统申请分配size个连续的内存空间。但是不会把分配的空间清0
返回值是void*

如:void *P=malloc(10);  //向系统分配10个字节的空间。
free(p);   //释放堆空间

char *str=malloc(8);
strcpy(str,”iPhone”);
free(str);

六、常用内存管理函数

1、memset函数的使用
void *memset(void *s,int c,size_t n);
s开始,长度为n的所有字节赋值为c。
通常用于清除结构体或者数组数据。

如:
typedef struct stu{
    char name[20];
    int age;
}Student;

Student *p=malloc(sizeof(Student));//开辟结构体大小的空间
memset(p,0,sizeof(Student)); //从首地址p开始,将开辟的空间清0

void *q=malloc(100);
memset(q+10,1,20); //从q+10地址开始,开辟20个字节,每个字节里赋值为1

你可能感兴趣的:(10.C语言指针3)