指针 指针数组 数组指针 二级指针 到底怎么指向?
一、本文研究:
指针数组 与 二级指针
二维数组 与 数组指针
一维数组 与 一级指针
上面的两两一对,而并不是指针数组、数组指针这俩一对,弄清楚这一点,就懂了一半了。
一个是数组 ,一个是指针
二、指针数组 与 二级指针
指针数组:是一个存放指针的数组,数组的每个元素都是指针变量
看下面例子,看懂就会了
#include <stdio.h>
int main(){
char *lines[5] = {
"COSC1283/1284",
"Programming",
"Techniques",
"is",
"great fun"
};
char *str1 = lines[1];
char *str2 = *(lines + 3);
char c1 = *(*(lines + 4) + 6);
char c2 = (*lines + 5)[5];
char c3 = *lines[0] + 2;
printf("str1 = %s\n", str1);
printf("str2 = %s\n", str2);
printf(" c1 = %c\n", c1);
printf(" c2 = %c\n", c2);
printf(" c3 = %c\n", c3);
return 0;
}
对照上面哪里不会看哪里
#include <stdio.h>
int main(){
char *string0 = "COSC1283/1284";
char *string1 = "Programming";
char *string2 = "Techniques";
char *string3 = "is";
char *string4 = "great fun";
char *lines[5];
lines[0] = string0;
lines[1] = string1;
lines[2] = string2;
lines[3] = string3;
lines[4] = string4;
char *str1 = lines[1];
char *str2 = *(lines + 3);
char c1 = *(*(lines + 4) + 6);
char c2 = (*lines + 5)[5];
char c3 = *lines[0] + 2;
printf("str1 = %s\n", str1);
printf("str2 = %s\n", str2);
printf(" c1 = %c\n", c1);
printf(" c2 = %c\n", c2);
printf(" c3 = %c\n", c3);
return 0;
}
为了突出说明二级指针,再来:
#include <stdio.h>
int main(){
char *lines[5] = {
"COSC1283/1284",
"Programming",
"Techniques",
"is",
"great fun"
};
char **p = lines; //p是二级指针
//line给p赋值,说明line是二级指针
char *str1 = p[2]; //这里修改成2了原理一样
char *str2 = *(p + 3);
char c1 = *(*(p + 4) + 6);
char c2 = (*p + 5)[5];
char c3 = *p[0] + 2;
printf("str1 = %s\n", str1);
printf("str2 = %s\n", str2);
printf(" c1 = %c\n", c1);
printf(" c2 = %c\n", c2);
printf(" c3 = %c\n", c3);
return 0;
}
- char *lines[5]定义了一个指针数组,它的每个元素的类型都是char 。在表达式中使用 lines时,它会转换为一个类型为char**的指针,这样lines就表示一个指向字符的指针,而**lines表示一个具体的字符,这一点很重要,读者一定要明白。
- lines 是二级指针,*(lines+i) 是一级指针,**(lines+i) 才是具体的字符。
深入理解,关于地址怎么指的,指哪去了。
注意,"line"使用的时候也被理解成指针,也就是我们定义的那个p
三、数组 和 数组指针
二维数组是怎么回事?
int a[3][4]各部分是怎么回事?
重点:"a"当作指针用
定义数组指针:
热知识:数组指针走一步是走一行,也就是从a[0] 走到 a[1]
注意:维度必须要有,也就是说,得让这个指针知道它一行能走多少。
举个例子:维度是4,也就是一步走4 == 一行走4个元素
int (*p)[4];
**
#include <stdio.h>
void func(int (*p)[4]) {
printf("%d\n", p[1][2]); //输出6
}
void func1(int (*p)[3]) { //改变维度了,也就是,分组这样了
//{{0,1,2},{3,4,5},{6,7,8},{9,10,11}}
print("%d\n", p[1][2]); //输出5
}
int main(){
int a[3][4]={{0,1,2,3},{4,5,6,7},{8,9,10,11}};
int(*p)[4];
int i,j;
p=a;
for(i=0; i<3; i++){
for(j=0; j<4; j++) printf("%2d ",*(*(p+i)+j));
printf("\n");
}
func(a);
func1(a);
return 0;
}
四、一维数组 与 一级指针
int a[10] = {0, 1, 2, 3, 4, 5, 6, 7}
int * p = a;//p指向数组a的首地址,即a[0]的地址
//第一种遍历
for (i = 0; i < 8; i ++ ) {
printf("%d", *p);
p ++ ; //指针每次向后移动一个来遍历数组
}
//第二种遍历
for (i = 0; i < 8; i ++ ) {
printf("%d", *(p + i )); //用增量来访问
}
四、总结
五、leetcode指针怎么用?
int** threeSum(int* nums, int numsSize, int* returnSize, int** returnColumnSizes){
}
- 参数里面的所有指针都不是二维数组,均是一维数组,这一点首先明白
- nums:一维数组传进来用一个一级指针接受一下一维数组的首地址
- numsSize:表示传进来的一维数组的长度,如果没有长度,只靠首地址,我们无法知道这个数组有多大
- returnSize:这是调用函数的时候传进来的一个整数的地址,为什么传这个整数地址呢,因为我们需要在函数里改变它的值。所以用指针接收这个地址,指向这块内存。使用的时候,例如:*returnSize = 3;
- returnColunmSizes:这是调用函数的时候传进来的一个一维数组的地址,一维数组本来就是一级指针,取地址加一级,所以用二级指针接受。为什么传这个一维数组的地址呢,因为我们需要在函数里改变它的值。所以用指针接收这个地址,指向这块内存。使用的时候,例如:(*returnColumnSizes)[*returnSize] = 3;
- (*returnColumnSizes)表示对returnColumnSizes解引用,二级指针解引用,成一级指针,也就是指向了该数组。[*returnSize]再次解引用。
- (*returnColumnSizes) 相当于 a
- (*returnColumnSizes)[returnSize] 相当于 a[2] (假设returnSize = 2)
- 看图: