目录
一、指针运算
+-整数
int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int i = 0;
int sz = sizeof(arr) / sizeof(arr[0]);
int* p = arr;
for (i = 0; i < sz; i++)
{
printf("%d ", *p);
p = p + 1;
}
return 0;
上面是打印出1-10
for (i = 0; i < 5; i++)
{
printf("%d ", *p);
p += 3;
}
上面是打印出13579。
-指针
int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
printf("%d\n", &arr[9] - &arr[0]);
会得到9。-指针就是两个指针间的元素个数。如果调换过来,&arr[0] - &arr[9],就是-9。
但是如果定义一个char类型的数组,然后去减int类型的arr。这样的结果不可预知,也是一个不可取的代码。两个类型不兼容,所以没有意义。
同样计算个数的还有别的方法
int my_strlen(char* str)
{
char* start = str;
char* end = str;
while (*end != '\0')
{
end++;
}
return end - start;
}
int main()
{
char arr[] = "zyd";
int len = my_strlen(arr);
printf("%d\n", len);
return 0;
}
指针的关系运算
for (vp = % value[N_VALUES]; vp > &value[0]; )
{
*--vp = 0;
}
for (vp = % value[N_VALUES - 1]; vp >= &value[0]; vp--)
{
*vp = 0;
}
上面两段代码看起来比较复杂,因为这是在写一种形式。第一段代码,vp这个指针变量指向数组的最后一个元素的后边一个,也就是越界了,但仍然可以这样写,进入循环后,它先--,回到数组的最后一个元素,然后解引用得到这个元素,所以它第一次也是从数组最后一个元素开始的;判断条件写> [0]是因为,如果vp可以取到数组第一个元素,那么进入循环后,--就到首元素左边了,也是越界了。
第二段代码,vp正常被初始化为数组最后一个元素,进入循环后,解引用得到最后一个元素,然后vp--,往前走一步,找到倒数第二个元素,它的判断条件是[0],也就是首元素,vp取到首元素时进入循环,解引用,然后--,不符合条件,最后跳出循环。
两个结果一样,在绝大部分的编译器上是可以顺利完成任务的。但是第二种不标准。第二种循环到最后会将values[-1] 与 [0] 对比,虽然最终会退出循环。
标准规定:
允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,但是不允许与指向第一个元素之前的那个内存位置的指针进行比较
二、指针和数组
int main()
{
int arr[10] = { 0 };
printf("%p\n", arr);//地址:只取首元素的地址
printf("%p\n", &arr[0]);//只取首元素地址
printf("%p\n", &arr);//取到了整个数组,但是显示的开始的地址
//所以它们三个显示的地址是一样的
return 0;
}
&arr-&数组名-数组名不是首元素的地址-数组名表示整个数组 - &数组名 取出的是整个数组的地址
sizeof(arr)- sizeof(数组名)- 数组名表示的整个数组 - sizeof(数组名)计算的是整个数组的大小
都算地址
arr / arr + 1 前进4
&arr[0] / &arr[0] + 1 前进4
&arr / &arr + 1 前进40,需要跨越一个数组
int arr[10] = { 0 };
int* p = arr;
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%p\n", p + i, &arr[i]);
}
无论是p+i,&arr[i],打印的地址都一样。用指针还是数组都一样。
int arr[10] = {0};
int* p = arr;
int i = 0;
for (i = 0; i < 10; i++)
{
*(p + i) = i;
printf("%d ", *(p + i));
printf("%d ", arr[i]);
//printf("%p\n", p + i, &arr[i]);
}
打印出来都是0到9。
数组可以通过指针来访问。但是指针和数组不一样,指针只能存放数组首元素地址,而数组可以存放所有元素地址。
三、二级指针
int a = 10;
int* pa = &a;
int** ppa = &pa;//二级指针
int*** pppa = &ppa;//三级指针
内存开辟空间,名为a,里面存放10,并且有一个属于a的地址1。pa指针变量,里面存放的是a的地址1,而pa也有地址2。依次类推。对于int后面的几颗*,应这样理解。int**,第二颗*表示ppa是指针变量,而第一个*连同int,表示它指向的pa变量是int*类型。
*ppa,解引用会输出pa,**ppa就会输出a的值。
数组名是数组首元素地址
四、指针数组
int a = 10, b = 20, c = 30;
//整形数组:存放整形
//字符数组:存放字符
//指针数组:存放指针
int* arr[3] = { &a, &b, &c };//指针数组
int i = 0;
for (i = 0; i < 3; i++)
{
printf("%d ", *(arr[i]));
}
return 0;
可以把地址放到数组里,也就是指针数组。
整形数组存放int类型,字符数组存放char,整形指针数组则存放int*。
这是初级指针,以后再写其他的。
结束。