函数参数传递、数组指针、二级指针、左值、引用
程序员文章站
2024-01-01 19:34:58
...
二维数组指针和二级指针区别
- 一方面便是二维数组的地址一定是连续的,而二级指针的地址不一定要连续。参考
- 可以把二维数组数组名看作一个二级指针常量。
数组(名)是右值,而指针是左值?
例:
数组和指针是等效关系不是等价关系,一说指针对象,而数组非对象。
二维数组分配与参数传递 ※
二维数组(指针)动态分配和释放
malloc工作只是开辟一块你要的内存(连续的),同时返回内存首字节的地址,但是他不限定你内存里的内容,malloc( 5*sizeof(char) ) 只是给你空出一段20字节的内存空间,并且给你他的首地址,而你实际要往内存里装什么,完全通过强制类型转换来限定,比如 int**p=(int**)malloc(n*sizeof(char*))
动态分配基本都要用到指针数组。
//二维未知
char **a;
int i;
a = (char **)malloc(sizeof(char *) * m); //分配指针数组
for(i=0; i<m; i++)
{
a[i] = (char *)malloc(sizeof(char) * n); //分配每个指针所指向的数组
}
printf("%d\n", sizeof(a)); //4,指针
printf("%d\n", sizeof(a[0])); //4,指针
for(i=0; i<m; i++)
{
free(a[i]);
}
free(a);
//二维未知,连续内存
char **a;
int i;
a = (char **)malloc(sizeof(char *) * m); //分配指针数组
a[0] = (char *)malloc(sizeof(char) * m * n);//一次性分配所有空间
for(i=1; i<m; i++)
{
a[i] = a[i-1] + n;
}//采用如上内存分配方法,意味着将a的值初始化为m*n的二维数组首地址,且这块内存连续
printf("%d\n", sizeof(a)); //4,指针
printf("%d\n", sizeof(a[0])); //4,指针
free(a[0]);
free(a);
二维数组指针p可以看做行指针。
静态二维数组传参实例
/*指定了列数*/
int fun(int a[][N])
{
printf("%d\n",a[i][j]);
}
/*未指定列数*/
int fun(int *a)
{
printf("%d", a[i*N + j]);//只能转成一维处理
}
指针的偏移量问题
-
指针的偏移量=指针的当前值+n*sizeof(指针指向的数据类型)
如 int (*a)[3]={0}; a是一个数组指针,a+1的偏移量是12个字节
又如 -
二维数组指针
int a[3][4],*p;
p=(int*)a;//将二维数组强制类型转化为一级指针,p++可以到12
左值和右值
左值(lvalue):一个标识非临时性对象的表达式。通常来说,可以将程序中所有带名字的变量看做左值。
右值(rvalue):相对的,右值标识是临时性对象的表达式,这类对象没有指定的变量名,都是临时计算生成的。
引用
(1)左值引用
左值引用的声明是通过在某个类型后放置一个符号&来进行的。前文代码中的int & y = x;便是一个左值引用。
需要注意的是,在定义左值引用时,=右边的要求是一个可修改的左值。
(2)右值引用(不常用)
类似于左值引用,右值引用便是对右值的引用,它是通过两个&&来声明的
引用和指针有什么区别
我们知道,指针是在内存中存放地址的一种变量,cpu能够直接通过而变量名访问唯一对应的内存单元,且每个内存单元的地址都是唯一的。
而变量名和引用,都可以看做内存的一个标签或是标识符,计算机通过是否符合标识符判断是否为目标内存,而一个内存可以有多个标识符
参考:https://www.cnblogs.com/Bylight/p/10530274.html