数组的指针

指向数组的指针

Int a[10] = {1,2,3,4,5,6,7,8,9,0}; &a是对a 这个一维整形数组取地址,就是a数组首元素a[0]的地址, 即 数组指针。

int * 型指针 p 不能存放 一维数组的地址,左右两边类型不匹配

如果要存放一维数组a的地址 应该 这样定义p

Int (*p)[10]; 这个指针的基类型是长度为10的一维整形数组。  

注意区分 int *p[10]; 这是定义了一个长度为10的 int *型的数组

当 初始化 int (*p)[10];时  p 与 p +1 ;地址相差 基类型 int [10]个字节即40个字节

如上图:要创造一个指针来装a[0]的地址则需要 使用 int (*p)[4]; 来初始化指针p

p = a 即 p指针里存放的是一个长度为四的整形一维数组a[0]。

当 p + 1 时 指针变量p将会加 int [4] 个字节 指向 a[1]的地址即a[1]的首地址。

// *( p + 1)  == p [1] == a[1]。

*(p + 1)的类型是 int * , 即指的是a[1]里首元素的地址。

*(p + 1) + 2, + 2 即向后偏移八个字节。在 *(p + 1 )的基础上

*(*(p + 1) +2) 是int型,打印出来指针指向的a[1][2]的值是7

// a[i][j]  <=> *(*(a+i)+j)  二维数组 用指针表示。

a[i] = *(a+i)  a[i][j] = *(*(a + i) + j)


第一个括号( a + 3 )  a 的类型为 与int (*p)[4] 相同的类型 即int * [4]  +3即是向后偏移 3 * 4 * 4 个字节, 第二个括号 (int *) 将(a + 3 )类型强转为 int * 型,整体 – 3 即向前偏移 3 * 4 个字节。指向a[2][1]  = 10。

二维数组的函数作为参数,形参为指向数组的指针本身。

值是一个指针的为 指针函数

动态内存分配

Void *malloc(size_t size); 函数

是 指针函数  需要包含头文件 <stdlib.h>

作用是分配一个连续的空间。 分配的空间 在 堆区. Malloc( )括号内空间的单位是字节数。

指针P 指向malloc分配的连续内存的首地址。分配的内存没有初始化全是随机数

Malloc 函数使用后 需要使用 free(p); 释放空间,p的地址必须是使用malloc时的地址,不能被修改,如必须修改,则先备份。

连续使用两次malloc 函数时,这两个空间一定不连续。

int * p = realloc(p, m * sizeof(int));

Static

修饰 变量 I 使i从动态生存期变为静态生存期,出了子函数不会被销毁。

可以使其出了函数可以被调用。 

返回值为指针的函数 不能返回 在函数内部定义的局部变量地址,因为在函数结束时会被销毁。

指针的指针

也称为二级指针

程序在第14-15行崩溃,S为野指针

指针 s 在调用 getMemory函数时 是进行的值传递,指针S没有初始化,在调用函数时,只是将s所指向的地址传给指针变量p, p是s的复制品。值传递不能在被调修改主调。

要在被调函数修改指针s:

被调函数 形参要修改为 char **p 函数中 p 修改为 *p

调用函数时要传递s的地址, &s

例:

 指针的数组

定义了一个指针数组,

数组中有十个指针, sizeof(a) 的 大小为80个字节。

指针数组作为函数参数传递,形参是指针的指针。

函数名 s <<==>>&s[0]  即数组名 就代表该数组的首元素地址

代码练习:

e1.实现二维数组的打印,累加,反转,通过传参数组指针实现。

void printArray2D(int (*a)[4], int rows)
{
    int i, j;
    for(i = 0; i < rows; ++i)
    {
        for(j = 0; j < 4; ++j)
        {
            printf("%d\n",*(*(a+i)+j));
        }
        printf("\n");
    }         
  
}

int sumOfArray2D(int (*a)[4], int rows)
{
	int cols = sizeof(*a) / sizeof(**a);
	int sum = 0, i = 0 , j = 0;
	for(i = 0; i < rows; ++i)
	{
		for(j = 0; j < cols; ++j)
		{
			if(0 == i || rows - 1 == i || 0 == j || cols - 1  == j)
			{
				sum += *((*a + i) + j);
			}
		}
	}
	return sum;
}

void swap(int *a, int *b)
{
	int t = *a;
	*a = *b;
	*b = t;
}

void reverse(int *begin, int *end)
{
	while(begin < end)
	{
		swap(begin,end);
		++begin;
		--end;
	}
}

void reverseArray2D(int (*a)[4], int rows)
{
	int cols = sizeof(*a) / sizeof(**a);
	int i = 0;
	while(i < rows)
	{
		reverse(*(a + i) ,*(a + i) + cols -1);
		++i;
	}
}



int main(int argc, const char *argv[])
{
	int a[][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
	int rows = sizeof(a) / sizeof(*a);
	int cols = sizeof(*a) / sizeof(**a);
//	reverseArray2D(a,rows);
	reverse(*(a+1),*(a + 1) + cols -1);
	printArray2D(a,rows);
//	int sum = sumOfArray2D(a,rows);
//	printf("%d\n",sum);
	return 0;
}

  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值