指针与数组

指针

  • 指针之间不同类型不能相加

  • 指针的类型很重要,决定指针的长度,解析方式

  • 指针的类型决定了指针从指针的值前进几个字节

  • 指针不能指向数据类型不同的数据

  • const在*左边,可以改变指向,不能修改所修饰变量的值,const在*的右边,不可改变指向,但可以修改值

  • const int * const p 指向和数据都不可以改变

  • 指针优先级

    • *p++,++先执行
    • ++p,p先执行,优先级接触生效
  • 指针与数组名

    • int a[10]={1,2,3,4,5,6,7,8,9,10}
      • a是一个指针,步长为4,&a是一个数组指针,步长为40,*a指向一列,步长为4
    • int b[3][4]={1,2,3,4,5,6,7,8,9,10,11,12}
      • b等价于行指针,步长为一行的大小,&b步长就是整个数组,*b步长为一列的一个元素,步长为4

二维数组

  • int a[10],a是int *指针, &a 是int (*)[10]类型,数组指针

  • int(*p)[5] = a+0;//二维数组名本质 -指向一个固定长度的数组的常量指针

  • int a[3][5],a int (*)[5],&a,int (*)[3][5]面指针, *a是int *指针

  • 二维数组等同于*(*(a+i)+j)

  • 数组优点便于查找, 删除,插入效率低

  • 链表,便于插入,删除,不方便查找

  • 分块数组,查找效率与数组一样,删除,插入,效率最高

    • 分块的数组可以等长,也可以不等长
  • 在栈上创建二维数组

    • 一维数组:int *p=(int []){0}
    • 二维数组:int (*px)[4]=(int [] [4]){0}
    • 三维数组:`int (*py)[3][4]=(int [] [3][4])
  • 堆上分配内存地址连续的二维数组

    void main4()  
    {  
        int(*p)[4] = malloc(sizeof(int)* 12);//连续  
      
        int num = 0;  
        for (int i = 0; i < 3; i++)  
        {  
            for (int j = 0; j < 4; j++)  
            {  
                printf("%4d", p[i][j] = num++);//  
            }  
            printf("\n");  
        }  
        free(p);  
      
        system("pause");  
      
    }  
    
  • 堆上分配内存地址不连续的二维数组

    void    main2()  
    {  
        int **pp = calloc(3, 4);//分配指针数组  
        for (int i = 0; i < 3;i++)  
        {  
            pp[i] = malloc(4 * sizeof(int));//每个指针分配内存  
        }  
        int num = 0;  
        for (int i = 0; i < 3;i++)  
        {  
            for (int j = 0; j < 4;j++)  
            {  
                printf("%4d",pp[i][j]=num++ );// *( *(pp+i)+j)  pp[i][j]  
                //*(pp+i)  ==pp[i]   pp+i  == &pp[i]  
            }  
            printf("\n");  
        }  
        for (int i = 0; i < 3;i++)//先释放块  
        {  
            free(pp[i]);  
        }  
        free( pp);//再释放指针数组  
      
        system("pause");  
    }  
    

N级指针

int **********pppppppppp = malloc(4*(sizeof(int *********)))

int*********ppppppppp =malloc(4*(sizeof(int ********))

N级指针,存储N-1级指针的地址

N级指针分配一个数组,存放N-1级指针

数据 0级指针

分块数组

void main()
{

	int **pp = malloc(sizeof(int *)* 5);//20个字节,
	//*(pp + 0)  pp[0]
	int num = 0;
	for (int i = 0; i < 5;i++)
	{

		pp[i] = malloc(sizeof(int)*(5+i));
		for (int j = 0; j < 5+i;j++)
		{
			pp[i][j] = num;//赋值
			num++;
		}

	}

	for (int i = 0; i < 5;i++)
	{
		for (int j = 0; j < 5+i; j++)
		{
			printf("%4d", pp[i][j]);
		}
		printf("\n");
	}

	system("pause");
}

二维数组本质

void main2()
{

	int  b[5];
	int a[3][5];
	printf("\n%p,%p", a, a + 1);//20个字节
	printf("\n%p,%p", *a, *a + 1);//4个字节
	//int ** p = a;
	int(*p)[5] = a+0;//二维数组名本质 -指向一个固定长度的数组的常量指针
	//a = 1;
	int  *px = *(a+0);//*a 4,  *a  就是int *
	int (*py)[3][5] =&a; //&a,一个指向固定长宽的二维数组的指针,二维数组指针


	system("pause");

	//int a[10],a是int *指针, &a 是int (*)[10]类型,数组指针
	//int a[3][5],a int (*)[5],&a,int (*)[3][5]面指针, *a是int *指针

}

遍历二维数组

void main1()
{
	int a[3][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0 };
	for (int i = 0; i < 3;i++)
    {
		for (int j = 0; j < 5;j++)
		{
			printf("%4d", a[i][j]);
		}
		printf("\n");
    }
	for (int *p = &a[0][0]; p < *a + 15; p++)//&a[0][0] 
	{
		printf("%4d,%p\n",*p,p );
	}
	printf("\n\n");
	for (int i = 0; i < 15;i++)
	{
		printf("%4d,%p\n", a[i / 5][i % 5],  &a[i / 5][i % 5]);//游戏
	}
	// 00  01   02  03    04  
	// 10  11  12 

	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 5; j++)
		{
			printf("%4d  %p", a[i][j], &a[i][j]);
		}
		printf("\n");
	}
	printf("\n");
	printf("\n");
	for (int i = 0; i < 3; i++)
	{
		printf("\na+%d=%p,%p", i, a + i, &a[i]);//a+i行指针   a + i, &a[i]
	}
	printf("\n");
	printf("\n");
	for (int j = 0; j < 5; j++)
	{
		printf("  %p   %p   \n", *(a + 0) + j, a[0] + j);// *(a + 0) + j,取地址,改变类型 a[0] + j
		printf("  %p   %p   \n", *(*(a + 0) + j), *(a[0] + j));

	}
	//a 行指针
	//a+i  &a[i]   第几行
	// *(a+i)  a[i]  第i行第0列地址
	//*(a+i)+j  a[i]+ k   第i行第j列地址
	//*(*(a+i)+j)  *(a[i]+ k )  第i行第j列地址
	system("pause");

}

指针数组与数组指针

数组指针:指向数组的指针

指针数组:数组中每个元素都是指针

void show(char * str[5])
{
	for (int i = 0; i < 5; i++)
	{
		printf("%s\n", str[i]);
	}

}

void show1(char ** str)//指针数组作为参数的时候,数组名的时候会退化为二级指针
{
	for (int i = 0; i < 5; i++)
	{
		printf("%s\n", str[i]);
	}

}
void main1()
{
//	int *a[10];
	//指针的数组的数组名是二级指针
	char * str[5] = {"calc","notepad","tasklist","mspaint","pause"};
	char **pp = str;
	//printf("%p", str);
	show1(str);

	system("pause");
}

动态数组

静态数组就是编译的时候就确定了大小:int a[10];

动态数组是申请堆上内存:
列必须确定的,行可以动态分配

void main1()
{
	//a[N]
	int N;
	scanf("%d", &N);

	int *p;

	p = malloc(sizeof(int)*N);

	for (int i = 0; i < N; i++)
	{
		p[i] = i;
		printf("\n%d", p[i]);
	}

	free(p);//释放内存
	//free(p);释放内存,只能释放一次,不可以反复释放

	system("pause");
}

void   main2()
{
	// int a[3][10]
	int(*p)[10] = malloc(sizeof(int)* 30);
	int num=0;
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 10;j++)
		{
			printf("%3d", p[i][j] = num++);
		}
		printf("\n");
	}
	system("pause");

}

void main3()
{
	int *p = malloc(3234567890);
	printf("%p", p);
	//分配成功返回首地址,
	//分配失败返回null
	system("pause");
}

void main4()
{


	//int *p = malloc(-1);//分配失败为0.-1补码

	int *p = malloc(0);

	printf("%p", p);//0能分配成功,没有意义

	system("pause");
}


void  run()
{
	void *p = malloc(10);//p占区

	//内存泄露,存储地址的指针消亡,就无法释放了
   //	free(p);
}


void  main()
{

	int(*p)[3][5] = malloc(sizeof(int)* 30);
	int num = 0;
	for (int i = 0; i < 2; i++)
	{
		for (int j = 0; j < 3; j++)
		{
			for (int k = 0; k < 5;k++)
			{
				printf("%4d", p[i][j][k] = num++);
			}
			printf("\n");
		}
		printf("\n\n");
	}

	system("pause");
}
posted @ 2016-11-17 20:41  呉语伦比  阅读(159)  评论(0)    收藏  举报