指针以及指针的运算

指针

指针的概念

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值