指针
例子
int是整型类型,存放一个数字的,例如1,2,3,4,5这些数字,而 int*就是一个整型的指针类型,是存放一个地址,但是这个地址指向整型的地址。
int *q;
代码如下(示例):
#include<stdio.h>
int main()
{
int *q;//q是指针变量, (int *)表示该q变量只能存放int类型的地址
int i = 10;
q = &i;
printf("%d\n",*q);
printf("%d\n",q);
return 0;
}
结果
解释
代码如下(示例):
*q 就代表指针指向i的地址,显示i的地址所存数据(10)
q 存储的是i的地址,因此输出数据为i的地址
指针:一个变量的地址称之为指针。2000H
指针变量:一个变量专门用来存放灵感一个变量的地址(指针),则他称之为指针变量。p
空指针:指针变量为零时,称为空指针(记为:NULL)。
注:参照指针指向的内容前,必须保证指针不是空指针,否则会引起系统死机,重启等重大问题。因此访问指针前的内容务必判断指针是否为空。
举个例子:
#include<stdio.h>
int main()
{
int a; //定义int形变量a
int *pa = &a; //&a是取a变量所在的地址,*pa:pa指向a的地址
a = 10; //设置a存储的值为10
printf("a:%d\n",a); //a的值:10
printf("*pa:%d\n",*pa); //取pa所指地址的值为10 pa指向a的地址
printf("&a:%x(hex)\n",&a); //a的地址为
printf("pa:%x(hex))\n",pa); //pa所存的值:pa里存的是a的地址
printf("&pa:%x(hex)\n",&pa);//pa的地址
return 0; //注:(hex)十六进制
}
结果:
图表示 :
辨析:*p++ *++p ++*p
前期知识:
#include<stdio.h>
int main()
{
int a[]= {0,1};
int *p = a;
printf("a[0]:%d\n",a[0]);
printf("a[0]地址:%d\n",&a[0]);
printf("a[1]:%d\n",a[1]);
printf("a[1]地址:%d\n",&a[1]);
printf("一个数组元素大小:%d\n",sizeof(a[0]));
printf("*p:%d\n",*p);
printf("*p+1:%d\n",*p+1);
printf("p:%d\n",p);
printf("p+1:%d\n",p+1);
}
可以看出 指针p +1 是增加一个int大小的长度,即4个子节(Byte)
优先级:
- ++为后置运算符 > ++为前置运算符和*运算符&运算符
- ++为前置运算符和 *运算符,& 运算符 的优先级相同
*p++
++
此时为 指针p
的后置运算符,++
为后置运算符的优先级 > *
运算符 &
运算符。先将指针p +1后取出指针p存储的地址所指的元素。
式子根据 i++,显示的是递增前的数值 即*p
递增前的数值。(表达式的值是 *p
递增前的值)
*p
此时增加1,*p
指向了a[2]
,p存储a[2]
的地址
*++p
++
对于p来说是前置运算符,++
为前置运算符优先级和*
运算符&
运算符相同,计算*
运算,*
取的值是++p
所存储的地址所指的值。
式子根据++i,显示的是递增后的数值 即p
递增后的数值。(表达式的值是p递增后的值)
*p
此时增加1,*p
指向了a[2]
,p
存储a[2]
的地址
++*p
++
此时为前置运算符,++
为前置运算符优先级 和*
运算符&
运算符相同,
先取*p
的值后+1
式子根据++i,显示的是递增后的数值 即*p
递增后的数值。(表达式的值是*p递增后的值) *p所代表指向的位置不变。
#include<stdio.h>
void show(int x[]){ //依次输出数组元素
int i;
for(i = 0;i<5;i++){
printf("x[%d]:%d\n",i,x[i]);
}
}
void dzshow(int x[]){ //依次输出数组元素地址
int i;
for(i = 0;i<5;i++){
printf("x[%d]:%d\n",i,&x[i]);
}
}
void pzshow(int *p){ //输出 *p
printf("*p:%d\n",*p);
}
void pshow(int *p){ //输出指针p中存储的值
printf("p:%d\n",p);
}
void pz2show(int *p){ //输出*p++
printf("*p++:%d\n",*p++);
printf("p:%d\n",p);
printf("*p:%d\n",*p);
}
void pz3show(int *p){ //输出*++p
printf("*++p:%d\n",*++p);
printf("p:%d\n",p);
printf("*p:%d\n",*p);
}
void pz4show(int *p){ //输出++*p
printf("++*p:%d\n",++*p);
printf("p:%d\n",p);
printf("*p:%d\n",*p);
}
int main()
{
int a[5] = {10,20,30,40,50}; //定义int类型数组
int *p; //定义int类型指针p
p = &a[1]; //指针p指向a[1]
int length = sizeof(a)/sizeof(a[0]); //计算数组长度
printf("个数:%d个\n",length);
show(a,length); //数组元素分别输出
printf("<====================>\n");
dzshow(a); //数组元素地址输出
pzshow(p); //指针p所指对象输出 即a[1]
printf("*p:%d\n",*p);
pshow(p); //指针p存的值输出
printf("p:%d\n",p);
printf("====================\n");
printf("优先级:++为后置运算符 > ++为前置运算符和*运算符&运算符, ++为前置运算符和*运算符&运算符优先级相同 \n");
printf("====================\n");
printf("*P++\n");
show(a,length); //用来显示数组a是否发生变化
pz2show(p); //先执行*p(把p指的元素取出来)再执行++。//根据i++,显示的是递增前的数值 即*p递增前的数值。(表达式的值是*p递增前的值) *p此时增加1,*p指向了a[2],p存储a[2]的地址
show(a,length); //用来显示数组a是否发生变化
printf("====================\n");
printf("*++P\n");
show(a,length); //用来显示数组a是否发生变化
pz3show(p); //先指针p进行+1,再取出内容。//根据++i,显示的是递增后的数值 即*p递增后的数值。(表达式的值是*p递增后的值) *p此时增加1,*p指向了a[2],p存储a[2]的地址
show(a,length); //用来显示数组a是否发生变化
printf("====================\n");
printf("++*P\n");
show(a,length); //用来显示数组a是否发生变化
pz4show(p); //先*运算取出指针p的值,*p=20 之后+1,*p=21 ,根据++i,显示的是递增后的数值 即*p递增后的数值。(表达式的值是*p递增后的值) *p所代表指向的位置不变。
show(a,length); //用来显示数组a是否发生变化 数组a[]已经变化了
return 0;
}
字符串
字符串内部实现:
\0 为字符串结束标记
C语言实现
代码如下(示例):
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
char *p;
p = (char *)malloc(20*sizeof(char)); //动态分配10个连续的字符空间 malloc函数由<stdlib.h>头文件提供
strcpy(p,"hello world"); //字符串处理所需的库函数(例:strcpy)由<string.h>头文件提供
将hello world存放到p所指向的空间中
printf("%c\n",*p); //输出字符h
printf("%s\n",p); //输出字符串hello world
free(p); //释放p指向的空间
return 0;
}
解释
过程解释:
- 先分配空间叫指针p
- 在主存里面分配20个连续的字符空间
- 将连续空间的首地址存储到指针p中
- strcpy将 hello world(常量) 存储到空间中去
- 输出字符c(因为输出的类型是char类型,因此只能输出一个字符,即h)
- 输出字符串hello world(依次从空间的首地址开始,依次输出,直到遇到 \0符 停止)
- 最后释放p指向的空间。(不是释放p)
结果: