指针的概念
指针有很多层意义,这就是混乱的根源
我们可以使用地址,数值,指针或变量
指针的用法
注意:
在指针中只能存储地址。
int number = 0;
number = 10;
int *pnumber = NULL;
pnumber = &number
赋值运算符将在变量中存储值10,
使用寻址运算符获取变量number的地址,将该地址存储到指针中。存储在pnumber中的值是number的地址,用指针变量名pnumber访问这个地址。
测试NULL指针
if(!pvalue)
{
//tell everyone!-the pointer is NULL!
//pvalue是NULL;测试!pvalue就是ture,所以这段语句只有只有pvalue是NULL时才会执行。
}
NULL常常定义为((void*)0),即给指针赋予0时,等于NULL
int *pvalue = 0;
if(pvalue == NULL)
{
//tell everyone!- the pointer is NULL!
}
指针的工作原理
存储在pnumber中的地址是number第一个字节的地址
使用指针
- 创建指针变量
- 创建类型char的变量
- 存储pChar中变量的地址
- 间接存储变量中的值
#include <stdio.h>
int main()
{
char *pChar = NULL;
char ch = 0;
pChar = &ch;//赋值运算符
*pChar = 'a';
printf("%p\n",pChar);
printf("%d\n",*pChar);
return 0;
}
警告:
声明指针时,一定要初始化它们,使用未初始化的指针存储数据项是很危险的。
如何通过指针访问变量的内容?
#include <stdio.h>
int main()
{
int number = 999;
int *pNumber = NULL;
pNumber = &number;
*pNumber += 25;
printf("%d\n",*pNumber);
return 0;
}
星号*表示访问pnumber变量所指向的内容
*运算符的作用是访问存储在指针中的地址的数据。
*pNumber += 25;
变量 pnumber 所指向 的地址中的 值 增加25
指针可以包含同一类型的任意变量的地址
所以指针变量可以改变其他许多变量的值,只要类型和指针相同
指向常量的指针
通过小例子说明执行过程,巩固知识点,以后不要在单一的只是学习(或者死记硬背知识点)。把学到的知识试着去运用。
#include <stdio.h>
int main()
{
long value = 9999L;
const long *pvalue = &value;
pvalue = 8888L;//错误的(不能通过指针直接改变它指向的值
value = 8888L;//可以改变指针的地址的值
printf("%d\n",*pvalue);
return 0;
}
long value = 9999L;
const long *pvalue = &value;
**
> 指针指向的值不能改变
**
指向常量的常量指针
int item = 25;
const int *const pitem = &item;
**
> pitem是一个指向常量的常量指针
> 不能改变存储在指针pitem中的地址、也不能使用指针pitem改变指针指向的内容
**
常量指针
int count = 43;
int *const pcount = &count;
**
> 指定pcount指针存储的地址不能改变
**
7.2 数组和指针
使用scanf_s()读入一个字符
char single = 0;
scanf_s("%c",&single,sizeof(single));
使用scanf_s()读取字符串
char multiple[10];
scanf_s("%s",multiple,sizeof(multiple));
数组名称multiple等于数组第一个字节的地址
&multiple[0]等于数组第一个元素的第一个字节
multiple[n]与*(multiple +n)
*(p+n)是给p中的地址加上整数n,在对得到的地址取消引用
给地址值加1时,就表示要访问该类型的下一个变量
这就是为什么声明一个指针时,必须指定该指针指向的变量类型
多维数组
如何访问二维数组
数组名称[索引值]
board 的地址和 board[0]的地址相同
二维数组的数组名称,引用二维数组的开始地址
board是char型二维数组的地址
board[0]是char型一维子数组的地址,board的子数组
board[0][0]是char型数组元素的地址
如何得到二维数组的值
*(*board+0)==board[0][0] == *(pborad+0)
*(*board+1)==board[0][1] == *(pborad+1)
*(*board+2)==board[0][2] == *(pborad+2)
*(*board+3)==board[1][0] == *(pborad+3)
*(*board+4)==board[1][1] == *(pborad+4)
*(*board+5)==board[1][2] == *(pborad+5)
*(*board+6)==board[2][0] == *(pborad+6)
*(*board+7)==board[2][1] == *(pborad+7)
*(*board+8)==board[2][2] == *(pborad+8)
表达式*(*board+i)表示二维数组的元素值
(*board +i)括号中的表达式会得到数组中偏移量为i的元素的地址
只使用board,就是在使用 char** 类型的地址值,取消对board的引用,会得到相同的地址值,但其类型是 char*。给它加i会得到一个char*地址,它是内存中的第i个元素,即数组中的一个字符。取消对它的引用,会得到该地址中存储的内容。
board - char**类型的地址值 指针的指针(指向char*指针)
*board -- char*类型的地址值 指向char的指针
*(*board +i)是地址(*board+ i)的内容
char *pboard = &board[0][0];
char *pboard = *board
用以上两种方法初始化指针的效果相同
board 的地址和 子数组board[0]地址相同
声明并创建一个指针变量
unsigned long long pPrimes = NULL;
*(pPrimes +1) =2
*(pPrimes +2) = 3
*(pPrimes +3)
指针和字符串
用字符数组来存储字符串。
定义一个指针指向用来存放字符串的字符数组
一个字符串若被赋给一个字符型数组,则数组名表示字符串的的首地址,将字符指针指向该数组
char *p = "abcd";
定义一个字符指针,将字符串的第一个字符a的首地址付给指针p
利用gets_s()函数实现字符串的输入
利用for循环使指针指向字符串a1的末尾
定义两个字符指针p1和p2,分别指向数组a1和a2的首地址
char *p1 = a1;
char *p2 = a2;
指针的注意事项
注意1:
用指针输出数据时,要在指针前加上*号。
不加星号*,输出的的是变量的地址。()
只有加上*号,输出的才是变量地址中的内容。
注意2:
递增运算符和取消引用运算符的优先级是一样的,从右到左。
注意3:
p = &a;
将变量的地址赋值给p,即使指针p指向变量的a的内存地址,
int i;
int *p = &i;
*p = 3;
指针变量赋值后还可以改变变量的值。
*p++ 是先取出*p的值,再使p + 1;
(*p)++ 是使*p的值加 1;
*(p++) 等价于*p++,是先取出 *p 的值,再使p + 1;
++运算符前置,使用前:
++运算符后置,使用后:先使用,后加1
>
int main()
{
int x =3;
int *p,*q;
printf("%d\n",*p++);
printf("%d\n",(*q)++);
printf("%d",x);