1.指针家族:
指针有很多种类型:字符指针,数组指针,指针数组指针,整形指针等等
首先来了解一下指针的概念:
* 指针也是变量,只不过它是用来存地址的
* 指针的大小是固定的,在32位平台上是4个字节,在64位平台上是8个字节
* 指针有类型,指针的类型决定了指针加减整数的步长,即指针加一减一就是加上或减去其所指类型的大小。
* 指针的运算
2. 字符指针(char *)
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
int main()
{
char ch = 'w';//变量ch的初始化
char *pc = &ch;//把ch的地址存在字符指针pc中
*pc = 'M';//对pc解引用就是ch,再将M赋给ch
return 0;
}
上面这段代码定义了字符型变量ch,定义了字符型指针pc,并通过对指针解引用修改ch中的值。
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
int main()
{
char *pstr = "hello world.";
printf("%s\n", pstr);
system("pause");
return 0;
}
这段代码是直接将字符串放在pstr这个指针变量中吗?不是的这里指针变量只是保存了字符串首字符(h)的地址。
*有这样一道例题:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
int main()
{
char str1[] = "hello world";
char str2[] = "hello world";
char *str3 = "hello world";
char *str4 = "hello world";
if (str1 == str2)//组名代表数组首元素地址
{
printf("str1 and str2 are same\n");
}
else
{
printf("str1 and str2 are not same\n");
}
if (str3 == str4)
{
printf("str3 and str4 are same\n");
}
else
{
printf("str3 and str4 are not same\n");
}
system("pause");
return 0;
}
上面这段代码输出的结果是什么呢?首先来分析str1和str2这两个相等吗?答案是不相等,为什么?因为str1和str2是两个不同的数组(在栈上开辟空间),只不过这两个数组的内容一样罢了,所以str1 and str2 are not same,再来分析一下str3和str4,他们俩相等吗?首先他们都是指针变量,其次他们都保存了字符串首元素的地址,所以他们都指向同一个字符串,并且这个字符串存放在字符常量区(只读不可以改),故str3 and str4 are same.
3.指针数组和数组指针
首先看到这两个名字就有点傻傻分不清,是数组还是指针?其实不难,看最后两个字,就决定了它是数组还是指针,所以要准确区分二者也不是很难,下面有几个例子,我们一起来看一下:
int main()
{
int *arr1[10];//整形指针数组
char *arr2[4];//一级字符指针的数组
char **arr3[5];//二级字符指针的数组
system("pause");
return 0;
}
判断是数组还是指针方法如下:
根据优先性,看变量名跟谁先结合,跟中括号先结合就是数组,剩下的是指针的话,那就叫指针数组,如果先和结合,那就是指针,什么指针呢?那就看剩下什么了,剩下数组的话,就叫数组指针。
int * p1[10]; 显然p1先和[ ]结合,所以它是一个数组,剩下了 int * 所以它就是一个指向整形的指针的数组
int ( p1)[10]; 和上面不一样的是,这里p1先和 *结合,因为()的优先级高于[],所以这是一个指针,指向有10个整形的数组,所以这是一个数组指针。
4.&数组名和数组名
*在两种情况下数组名代表整个数组:sizeof(数组名) ,&数组名 其它情况下代表数组首元素地址。
先来看代码:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
int main()
{
int arr[10] = { 0 };
printf("%p\n", arr);
printf("%p\n", &arr);
system("pause");
return 0;
}
显然输出的结果应该是一样的,&arr代表的是数组的地址,arr代表数组首元素的地址,虽然值一样但是代表的意义不一样,这一点应非常清楚,那么给它们分别加一呢?
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
int main()
{
int arr[10] = { 0 };
printf("arr=%p\n", arr);
printf("&arr=%p\n", &arr);
printf("arr+1=%p\n", arr + 1);
printf("&arr+1=%p\n", &arr + 1);
system("pause");
return 0;
}
输出的结果又是怎么样的呢?

从输出结果来分析,arr+1只加了4,而&arr+1却加了40换成十六进制就是28,所以&arr+1实际上是加了整个数组的大小。
4.数组指针的使用
假如有一个数组arr初始化10个元素都为0,接着int (*p)[10]=&arr这里定义了一个数组指针,并把数组的地址赋给了指针变量,那么换一种形式 int (*p)[10]=arr 这样写可不可以?注意这里赋值两边类型要一致,这样写在编译时没有任何问题,因为左边是一个指针变量大小为四个字节,把数组首元素的地址赋值给这个变量没有问题,但是在运行是就会报错。
注意:数组传参时会发生降维,降维成指向其内部元素类型的指针。
5.函数指针
首先既然是函数指针那就对应函数的地址,函数的地址就是函数名或&函数名。
另外一个问题就是,在程序执行过程中,cpu是如何知道执行下一条指令?原来在cpu内部有一个pc指针,是cpu内部的一个寄存器,pc里面放的是当前正在执行指令的下一条指令的地址。
379

被折叠的 条评论
为什么被折叠?



