指针与数组

刚开始学二维数组的时候,各种带括号的 * 和不带括号的 * 再加上数组下标[ ]让人痛不欲生……

但是想了半个月之后,我突然明白了他们的关系,所以特意梳理出来,希望能帮到想我之前一样的初学者们~

首先,先弄清几个基本的知识:

  1. 指针的双重性质

不同于我们之前的数据类型,指针包含了两重含义:第一,它本身是常量还是变量;第二,它所指向的是一个常量还是一个变量。

也就是说,如果指针本身是一个常量,那么它所指向的内容就是固定的,永远只能指向那一个数据,不可以被修改成指向其他的数据;如果指针指向的是一个常量,那么就不可以通过指针来对这个常量进行修改,但是如果这个指针本身是一个变量,那么就可以使它再指向另外的数据。

假如我们这样声明一个指针:

1.const int * ptr(等同于int const*ptr),那么这代表这个指针是一个指向常量的变量指针,不可以通过指针的间接访问来修改所指向的值。

int main() {
	const int*ptr;
	int number=5;
	ptr=&number;
	
	(*ptr)++;		试图通过指针间接访问来修改number的值
	
	printf("%d\n",number);
	
	return 0;
}

尝试编译运行,就会看到编译器报错:“increment of read-only location”。当然了,常量是不能进行写操作,而只能进行读操作。

但是值得注意的是,number本身是一个变量,不代表它的值不可以变化,但是只能通过number直接修改,比如number++,这样是不会报错的。

2.int*const ptr 这是一个指向变量的常量指针,不能再让这个指针指向别的量了。这种常量指针一定要在声明的时候同时进行初始化!

int main() {
	int number1=5,number2=10;
	int*const ptr=&number1;
	
	ptr=&number2;
	
	return 0;
}

这样也会报错,“assignment of read-only variable”。

  1. 运算符的优先级问题

相信很多人一开始接触指针的时候,都搞不明白这样一个事情:

int ( * matrix) [50] 和 int * matrix [50]

究竟有什么区别??

要弄明白这个事,首先要知道数组下标[ ]的优先级是高于 * 的!

所以,如果不加括号,那么matrix会先与[50]结合,然后整体再与 int * 结合,也就是形成了一个数组,数组的类型是int*,也就是50个指向int类型的指针,matrix是这个数组指针的首地址。也就是说,这不过是一个基类型是int*的一个数组而已,这些数组中的元素在内存中都是连续的,但是指向的内容不一定在内存中连续。

加上括号之后,matrix先与int* 结合,那这个时候matrix代表了什么呢?如果我们把 *matrix这个东西看做一个整体,比如将它替换成variable,那么原来的式子就变成了int variable[50],就是一个普通的数组,variable是数组的首地址。而 * matrix=variable,所以,matrix就是一个指向数组首地址的指针!!!,相当于一个二维指针。

想明白这一点,你就会知道为什么int ( * matrix) [50] 这种形式可以用作函数中二维数组的参数啦!当然,在数组下标(最后一个)中的数字是不可以省略的!

但是二维数组int matrix[10] [50] 就等同于int ( * matrix) [50]吗?

二者仍然有区别的!

要知道,不管是维数多大的数组,它在内存中永远都是一维的线性表示的,也就是在内存中以连续的地址表示。就是说matrix[0][49]后面就是matrix[1][0]。

但是在int ( * matrix) [50]中,从matrix[0][0]到matrix[0][49]确实是连续的,但是matrix[0][49]跟matrix[1][0]却不一定连续!,但是matrix[1][0]到matrix[1][49]却也是连续的,以此类推。

  1. 动态分配二维数组

我们先来看两个函数原型:

spin_matrix(int(*matrix)[20],int row,int col);

spin_matrix(int**matrix,int row,int col);

其实只从函数原型来看,我们也大体可以确定第一个是静态分配在栈上的数组,而后者是动态分配在堆上的数组。

那么究竟如何对二维数组进行动态分配呢?


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

int main() {
	int**matrix;
	int row,col;
	int i,j;
	
	scanf("%d%d",&row,&col);
	
	matrix=(int**)malloc(sizeof(int*)*row);
	for(i=0;i<row;i++) {
		matrix[i]=(int*)malloc(sizeof(int)*col);
	}
	return 0;
}

每次动态分配都不要忘记最后还要手动收回!不过收回的时候要先回收matrix [i],最后再回收matrix,否则会导致matrix[i]找不到,就成了内存垃圾。


for(i=0;i<row;i++) {
		free(matrix[i]);
	}
	free(matrix);

4.二维数组作为函数参数

今天在做一道矩阵乘法的题目的时候,想用动态分配,把分配和输入的两个部分一起做了一个函数,但是一开始我的函数原型是这样的:

void get_matrix(int**matrix1,int**matrix2,int**result,int size);

没错……我忘记了对matrix进行动态分配的时候matrix的值发生了变化,**如果不按地址传递,变化是传不回main函数中的!**也就是说数组实际上还是相当于没有分配内存!!

所以最后这部分的函数应该写成:

void get_matrix(int***matrix1,int***matrix2,int***result,int size) {
    int i,j;

    *matrix1=malloc(sizeof(int*)*size);
    *matrix2=malloc(sizeof(int*)*size);
    *result=malloc(sizeof(int*)*size);

    for(i=0;i<size;i++) {
        (*matrix1)[i]=malloc(sizeof(int)*size);
        (*matrix2)[i]=malloc(sizeof(int)*size);
        (*result)[i]=malloc(sizeof(int)*size);
    }

    for(i=0;i<size;i++) {
        for(j=0;j<size;j++) {
            scanf("%d",&(*matrix1)[i][j]);
        }
    }
    for(i=0;i<size;i++) {
        for(j=0;j<size;j++) {
            scanf("%d",&(*matrix2)[i][j]);
        }
    }

    return;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值