指针见解(一)


前言

指针是C和C++的灵魂,这是毋庸置疑的。但对初学者来说这是比较吃力的,这里我分享我学习指针的笔记和见解。


一、指针是什么?

指针是什么呢?
我给出答案是:指针就是地址,地址也就是指针。这时,你或许还不知道何为地址。我们用更加通俗的语言来概括,地址:就是内存单元的编号。

指针变量?
指针变量就是存放地址的变量
通常我们叙述时会把指针变量简称为指针,实际它们含义并不一样

为什么叫指针?
我们知道int 变量存的是 int 类型的值,char 变量存的是 char 类型的值,而指针,它是一种特殊的变量,存的是内存地址,按照这个模板可以把它理解为:“内存地址变量” 存的是 “内存地址”,等价于:“指针变量” 存的是 “内存地址”

操作系统进行资源调度时,会根据这些变量存的地址去<请求和使用>那个地址代表的内存区域,这就像是这个变量存的地址指向了某片内存,人们用 “指针” 来统称所谓的 “内存地址变量”

1.1 指针的声明

int*    p;    /* 一个整型的指针 */
double* p;    /* 一个 double 型的指针 */
float*  p;    /* 一个浮点型的指针 */
char*   p;    /* 一个字符型的指针 */
  • 以int* p为例,int*代表整型变量的指针(数据类型),p是指针名。
    下面我们给出一个小例子:
#include <stdio.h>
int main ()
{
    
    
   int  a = 20;   /* 实际整型变量的声明 */
   int  *p;        /* 整型指针变量的声明 */
   p = &a;  /* 在指针变量中存储 var 的地址 */
   printf("a 变量的地址: %p\n", &a  );
   /* 在指针变量中存储的地址 */
   printf("p 变量存储的地址: %p\n", p );
   /* 使用指针访问值 */
   printf("*p 变量的值: %d\n", *p );
   return 0;
}

这里我们得到:
a 变量的地址: 0x7fff679edda4
p 变量存储的地址: 0x7fff679edda4
*p 变量的值: 20

1.2 空指针

在变量声明的时候,如果没有确切的地址可以赋值,为指针变量赋一个 NULL 值是一个良好的编程习惯。赋为 NULL 值的指针被称为空指针。
使用方法如下:

int  *p = NULL;

在大多数的操作系统上,程序不允许访问地址为 0 的内存,因为该内存是操作系统保留的。然而,内存地址 0 有特别重要的意义,它表明该指针不指向一个可访问的内存位置。但按照惯例,如果指针包含空值(零值),则假定它不指向任何东西。
如果要检查一个空指针,可以使用if进行如下操作:

if(p)     
if(!p)    

1.3 通过指针访问数组元素

观测下面两个程序都可以访问数组元素:

#include <stdio.h>

int main()
{
    
    
 int i, *p, a[] = {
    
    3,4,2,5,7,3,7,1,4,6}; 
 p = a;
 for (i = 0; i <= 9; i++) 
	{
    
     
		 printf("%d\n", p[i]); 
	}
   
   return 0;
}
#include <stdio.h>

int main()
{
    
    
 int i, *p, a[] = {
    
    3,4,2,5,7,3,7,1,4,6}; 
	p=a;
	for (i = 0; i <= 9; i++) 
		{
    
     
 			printf("%d\n", *(p+i)); 
		}
   return 0;
}
  • 这里:p[i],*(p+i)处,指针 p 的值是使终没有改变。所以
    变量指针 p 与数组名 a 可以互换。
    两个程序中:p=a;是把数组名赋值给指针,这里的数组名就是这个数组的首地址,所以就是把数组a[]的首地址存到指针变量p里面。
  • 那么数组名是否就是指针呢?我们再通过一个程序来辨别数组名和指针的区别
  • 这一段代码依旧能够将数组各元素输出,这是利用了指针:p++操作,我们可以进一步尝试用数组名a++会发现程序会报错。
  • 所以指针和数组名是不同的
  • 其实这段程序中的p是指针变量,而数组名只是一个指针常量。
  • 变量是可以修改的,常量是不可以修改的。
#include <stdio.h>

int main()
{
    
    
 int i, *p, a[] = {
    
    3,4,2,5,7,3,7,1,4,6}; 
	p=a;
	for (i = 0; i <= 9; i++) 
		{
    
     
 			printf("%d\n", *p); 
		p++;
		}
   return 0;
}
  • 同样的,我们观测下面程序,我们在int * 和指针变量p中间加入一个const,使p指针成为常量指针。
  • 这种情况下,p指针和数组名就没有什么不同的了。
#include <stdio.h>

int main()
{
    
    
    int i, a[] = {
    
    1,2,3,4,5}; 
	int *const p = a; 
	for (i = 0; i < 5; i++) 
		{
    
     
			 printf("%d\n", *p); 
 			 p++ ; /*注意这里,指针值被修改*/ 
		}
}

1.4 指针常量和常量指针

  • 对于一个整型变量:

如:int i = 0;我们可以重新对i赋值,因为i是一个变量.
那如果声明时就给它一个初始值,而在其它任何地方都不允许修改此值,可以在在int前或后加一个const,如:
const int i =10;或int const i =10;它们表示的意思是一样的。

  • 对于指针int *,const在前或在后是不一样的,

我们将int * const p称为指针常量即指针类型的而常量,它的特别之处在于其指向的地址不能改,但其指向的地址存储的变量能够改
同理,我们将const int *p称为常量指针,它的特别之处在于其指向的地址可以改,但其指向的地址存储的变量不能改

  • 示例:
#include <stdio.h>

int main()
{
    
    
    int a = 10; 
	int b = 20; 
	int* const p = &a; 
	//p = &b; /* 指针指向的地址不可以改*/ 
	a = 30;  /* 内容能改*/ 
	printf("%d\n", *p);
}
#include <stdio.h>

int main()
{
    
    
    int a = 10; 
	int b = 20; 
	const int *p = &a; 
	p = &b; /* 指针指向的地址可以改*/ 
	//b = 30;  /* 内容不能改*/ 
	printf("%d\n", *p);
}

总结

期待大家和我交流,留言或者私信,一起学习,一起进步!

猜你喜欢

转载自blog.csdn.net/CltCj/article/details/120442962