指针
指针的概念
In computer science, a pointer is a programming language object that stores the memory address of another value located in computer memory. A pointer references a location in memory, and obtaining the value stored at that location is known as dereferencing the pointer. As an analogy, a page number in a book’s index could be considered a pointer to the corresponding page; dereferencing such a pointer would be done by flipping to the page with the given page number and reading the text found on that page. The actual format and content of a pointer variable is dependent on the underlying computer architecture.
在计算机科学中,指针是编程语言中的一个概念,用于存储位于计算机内存中的另一个变量的内存地址。 指针引用内存中的某个位置,而获取存储在该位置的值称为解引用。 打个比方,一本书的目录中的页码可以视为指向相应页面的指针; 要解引用此类指针,可以通过把书翻到对应的页面并阅读在该页面上的内容来完成。
总结:指针是一个变量 ,用于存放内存单元中的地址
指针的声明格式
- Syntax: data_type *var_name
- data_type: 是指针所指向的元素的类型 ,其必须是C语言中有效的数据类型
- var-name: 是指针变量的名字
#inlude <stdio.h>
int main()
{
int i = 0;
char c = 'A';
int *pi = &i;//定义了一个指针变量pi,它被用来指向一个整型变量i
char *pc = &c;//定义了一个指针变量pc,它被用来指向一个字符类型的变量c
return 0;
}
指针的类型的作用
- 指针的类型决定了指针移动的
步长
。
#include <stdio.h>
int main()
{
int n = 10;
char *pc = (char *) &n;
int *pi = &n;
printf("the address of n is: %p\n",&n);
printf("pc = %p\n",pc);
printf("pc+1 = %p\n",pc+1);
printf("pi = %p\n",pi);
printf("pi+1 = %p\n",pi+1);
return 0;
}
程序输出的结果:
the address of n is: 0076F70C
pc = 0076F70C
pc+1 = 0076F70D
pi = 0076F70C
pi+1 = 0076F710
分析:指针变量pc
是指向char
类型变量的指针变量,由于编译器在为char
类型的变量分配内存的时候会分配1
个字节。因此指针变量pc
移动的步长为sizeof(char)
,即步长为1
。同理,指针变量pi
是指向int
类型变量的指针变量,由于编译器在为int
类型的变量分配内存的时候会分配1
个字节。因此指针变量pc
移动的步长为sizeof(char)
,即步长为1
。
- 指针的类型决定了对指针进行
解引用
操作的时候有多大的权限(能操作几个字节)。e.g.对char *
的指针进行解引用操作只能访问1
个字节,而对int *
的指针解引用可以访问4
个字节
#include <stdio.h>
int main()
{
int n = 0x11223344;
char *pc = (char *)&n;
int *pi = &n;
*pc = 0;
printf("The value of n is %x\n",n);
*pi = 0x55667788;
printf("The value of n is %x\n",n);
return 0;
}
程序输出的结果:
The value of n is 0x11223300
The value of n is 0x55667788
分析:由于指针变量pc
的类型是char
,故我们在对指针变量pc
进行解引用操作的时只能访问1
个字节。又因为在windows
下面,在对变量进行存储的时候是按照小端存储
方式来进行存储。所以我们通过解引用操作将整型变量n
的第1
个字节修改为了0
之后对变量n
的值进行打印的时候我们得到的是0x11223300
。同理,由于指针变量pi
的类型是int
,所以我们在对指针变量pi
进行解引用操作的时候可以访问4
个字节。我们通过解引用操作将变量n的值修改为0x55667788
。
指针的运算
指针的算术运算
- 指针变量
±
整数
#include <stdio.h>
int main()
{
int arri[10] = {0};
int *pi = arri;
char arrc[10]={'a', 'b', 'c', 'd', 'e', 'f', 'g','h','i','j'};
char *pc = arrc;
printf("The value of pi is %p\n",pi);
printf("The value of pi+1 is %p\n",pi+1);
printf("The value of pi+2 is %p\n",pi+2);
printf("The value of pi is %p\n",pc);
printf("The value of pi+1 is %p\n",pc+1);
printf("The value of pi+2 is %p\n",pc+2);
}
程序输出的结果:
The value of pi+1 is 0067F7FC
The value of pi+2 is 0067F800
The value of pi is 0067F7D8
The value of pi+1 is 0067F7D9
The value of pi+2 is 0067F7DA
分析:由于指针变量pi
指向的变量类型是int
,所以对pi
进行算术运算的时候它的步长是4
,故pi+1
实际上指向的是数组中的元素arri[1]
,pi+2
指向的是数组arri
中的下标为2
的元素arri[2]
。同理,由于指针变量pc
指向的变量类型是char
,所以对pc
进行算术运算的时候它的步长是1
,故pc+1
实际上指向的是数组arrc
中的下标为1
的元素arrc[1]
,pc+2
指向的是数组arrc
中的下标为2
的元素arr[2]
。
结论:
pi ± 整数
会被编译器处理为pi ± 整数*sizeof(int)
- 指针变量 - 指针变量
#inlude <stdio.h>
int main()
{
int arri[10] = {0};
int *pi_start = arri;
int *pi_end = &arri[8];
char arrc[10]={'a', 'b', 'c', 'd', 'e', 'f', 'g','h','i','j'};
char *pc_start = arrc;
char *pc_end = &arrc[8];
printf("The value of pi_start is %p\n",pi_start);
printf("The value of pi_end is %p\n",pi_end);
printf("The value of pi_end-pi_start is %p\n",pi_end - pi_start);
printf("The value of pi_start is %p\n",pc_start);
printf("The value of pi_end is %p\n",pc_end);
printf("The value of pi_end-pi_start is %p\n",pc_end - pc_start);
}
程序输出的结果:
The value of pi_start is 0099F76C
The value of pi_end is 0099F78C
The value of pi_end-pi_start is 00000008
The value of pi_start is 0099F740
The value of pi_end is 0099F748
The value of pi_end-pi_start is 00000008
结论:
当两个指针指向同一数组中的元素的时候,我们可以通过两个指针相减来得到两个指针之间元素的个数。
pi_end - pi_start
会被编译器处理为(pi_end - pi_start)/sizeof(指针的类型)
指针的关系运算
- 对指向同一数组中的元素的两个指针可以执行
"<"
、"<="
、">"
、">="
这4
种关系运算。指针的关系运算表达式的结果会告诉参与运算的两个指针中哪个指针指向数组中更前或更后的元素。
#include<stdio.h>
int main()
{
char arrc[10]={'a', 'b', 'c', 'd', 'e', 'f', 'g','h','i','j'};
char *pc_start = arrc;
char *pc_end = &arrc[8];
if(pc_start < pc_end)
printf("pc_start更靠前!~\n");
if(pc_end > pc_start)
printf("pc_end更靠后!~\n");
}
程序输出的结果:
pc_start更靠前!~
pc_end更靠后!~
常量指针与指针常量
常量指针
- 定义格式:
const *
//const 在*的前面。 - 指针所指向的内存单元的内容不能被改变。
- 指针变量本身的内容可以被改变也即可以改变指针变量的指向。
#include<stdio.h>
int mian()
{
int x = 0, y = 0;
const int * p = &x;//定义一个常量指针p并让p指向变量x
p = &y;//改变常量指针的指向是合法的
*p = 20;//非法(不能修改常量指针所指向的内存单元的内容)
return 0;
}
指针常量
- 定义格式:
* const
//*在const的前面 - 指针变量本身的内容不可以被改变。
- 指针变量所指向的内存单元的内容可以被改变。
#include<stdio.h>
int main()
{
int x = 0, y = 0;
int * const p = &x;//指针常量在定义的时候要对其进行初始化
p = &y;//非法(不能改变常量指针的指向)
*p = 20;//指针变量所指向的内存单元的内容可以被改变
return 0;
}