认识指针变量

指针变量

1、指针的概念

什么是指针?一个内存变量或数组变量在内存中的地址就是指针,或者说,内存地址就是指针,指针就是内存地址。

2、指针变量的定义

指针变量的定义,其实就是在普通变量的变量的定义只多了一个*符号。

格式:

变量类型 * 指针变量名称[=地址];

例如:int i=0;
int *p=&i;//其中&符号是取地址符号,用于获取一个变量的地址。

注意:

  • *符号的左边和右边可以各有一个空格间隔,这样书写代码显得更清晰一些。

  • *符号两旁都没有空格或者左边或右边有一个空格都是可以的,就如同赋值符号两边可以有空格也可以没有空格一样。

测试指针变量空间大小的值

#include<stdio.h>
int main() {  
    int i = 0; int* p = &i;  
    printf("指针变量p的空间地址为%p\n",p); 
    printf("指针变量p的空间大小为%d\n",sizeof(p)); 
    return 0;
}

3、指针变量的功能

对所指向的内存地址上的数据进行读取或写入操作

测试指针变量的功能

#include<stdio.h>
int main() { 
int i = 0; int* p = &i;
printf("指针变量p的空间地址为%p\n",p); 
printf("指针变量p所指向的数据值:%d\n",*p);//输出结果0 
*p = 666; 
printf("指针变量p所指向的数据值: %d\n", *p);//输出结果666 
return 0;
}

4、指针变量与数组

指针变量也可以使用类似于数组的下标符号[],对目标内存(变量空间进行读或写的操作。

//例如:
int i=666;
int*p=&ip[0]=-1; //*p=-1; 这两种写法是等价的!

指针变量对目标内存空间进行读写操作的两种方式:

•通过指针变量与*符号对指向的内存操作;

•使用下标符号[]与指针变量联合来读写目标内存中的数据。

测试指针变量与数组

#include<stdio.h>
#include <stdlib.h>
int main(){  
int a[] = { 8,5,6,2,5 };
int i = 0;  int* p = a;  
while (i <sizeof(a)/sizeof(a[0]))  
printf("%d ", p[i++]); 
p = &i;  printf("\n数组元素的个数是:%d", p[0]); 
//p[0] 与 *p 是等价写法
printf("\n数组元素的个数是:%d", *p);    
//p[0] 与 *p 是等价写法 
return 0;
}

5、指针变量原则

对一个变量取地址的结果是指针常量,我们熟悉的一个数组名其实就是指针常量。

int a[10],i=10;
int *p = a; 
//数组a只能做右值不能做左值
p=&i; 
//&i也是只能做右值不能做左值,而可以做左值的p就是指针变量

5.1、指针变量的赋值原则

•右值必须是指针变量或者指针常量,不可以是一个整数或者浮点数。

int *p = 1; //错误:不能使用整数常量赋值
int i=2,*p1 = i; //错误: p1是指针变量,i是整型变量

•只有一个整数可以赋值给指针变量,那就是0,0代表空指针或空地址

int *p=0; //可以使用空地址对指针变量初始化

•右值必须是相同类型的指针变量或者常量(除非使用强制转换语句)。

int i = 1;int *p=&i; //正确:类型相同
char*pc =p; //错误:类型不同

• 同时定义两个指针变量时,每个指针变量前面都要带有*符号。

int i = 10; 
//int p1=&i,p2=p1; //错误:p2是int类型 
int *p1=&i,*p2=p1; //正确:p2是int类型

5.2、指针变量的使用原则

• 指针加减(p+n)

假如现在有一个未知类型的指针变量p和一个整型常量n。

那么思考:p+n之后的地址与p指向的地址之间,最终相差的物理距离是多少?

其实,p+n的地址偏移与指针变量的类型有关,请大家看下面的例子:

  • 如果是char*类型,p+n偏移n个字节;
#include <stdio.h>
int main(){ 
 char a = 'x';  
char* b = &a;  
int i = 0;  
for (i; i < 10;i++) {  
  char* p = b + i;  
  printf("指针变量p[%d]的地址是%p\n",i,p); 
 }  
return 0;
}
  • 如果是short* 类型,p+n偏移n*2个字节;
# include <stdio.h>
int main(){ 
 short a = 'x'; 
 short* b = &a; 
 int i = 0;
  for (i; i < 10;i++) {  
  short* p = b + i;  
  printf("指针变量p[%d]的地址是%p\n",i,p); 
 } 
 return 0;
}
  • 如果是int* 类型, p+n偏移n*4个字节
# include <stdio.h>
int main(){ 
int a = 100; 
int * b = &a;  
int i = 0;for (i; i < 10;i++) {  
int * p = b + i;   
printf("指针变量p[%d]的地址是%p\n",i,p); 
}  
return 0;
}
  • 如果是double* 类型,p+n偏移n*8个字节。
# include <stdio.h>
int main(){ 
double a = 100.00;
double * b = &a; 
int i = 0;for (i; i < 10;i++) {  
double * p = b + i; 
printf("指针变量p[%d]的地址是%p\n",i,p); 
} 
return 0;
}

6、指针变量做参数

C语言中,特殊类型的指针变量主要包括:常量指针、指针常量和无类型指针

•常量指针:指向常量区的指针变量

例如:const int* p;

•指针常量:指针变量中的常量

例如:int* const p;

•无类型指针:只记录地址不记录类型的指针变量

例如:void* p;

•常量指针

例如:const char* p;

常量指针的应用:

#include<stdio.h>
int main(){ 
 const int a[10] = { 8,12,38,54 }, b = a[4]; 
 const int* p = a;//常量指针 
 int i = 0; 
 while (*p)    
printf("%d ", *p++);  //*p = 10; 编译时报错! 
 p = &b; 
 printf("%d\n", *p);  //*p = 10; 编译时报错!
  return 0;
}

常量指针的特点:

Ⅰ、常量指针阻止修改指针指向内存的数值

例如:const char* p = "xiaokenan"; 
//字符串常量原本的类型就是常量指针的类

Ⅱ、常量指针禁止对目标数据赋值操作,允许读取操作,允许偏移操作

const char* p = "xiaokenan";
p = p+1; //可以,是允许指向变动的
char c = *p; //可以,只读
p[0] ='s'; //不可以,指针指向内存的数值是不允许被修改的

Ⅲ、常量指针最常用于做参数,目的保护被调函数内的实参,在被调函数执行过程中不被修改

#include<stdio.h>
int Calcal(const int* p) {
    int nSum = 0;
    while (*p)
        nSum += *p++;
    //*p = 6;//编译错误,不能修改!
    return nSum;
}
int main() {
    int a[] = { 123456 };
    int n = Calcal(a);
    printf("你输入的数字总和为:%d\n", n);
    return 0;
}

•指针常量

Ⅰ、定义指针常量的格式:类型 * const变量名=地址;

int n=10l;
int* const p=&n;//指针常量必须初始化

Ⅱ、指针常量的应用:

#include<stdio.h>
int main() {
	int a[] = { 123456 }, n = 666;
	//int * const p  错误:必须初始化
	int* const p = a;//常量指针
	//++p;  不可以,不能执行偏移操作
	//p = &n;  不可以,不能指向新的地址
	*p = n;  //可以,可以对目标内存执行写入操作
	printf("a[0]=%d\n", a[0]);
	return 0;
}

Ⅲ、指针常量的特点:

  • 指向固定的位置的指针变量,格式是const在指针变量前星号后。
int n=100; int* const p = &n;
  • 禁止偏移操作,允许对数据赋值操作和读取操作
p=p+1; //错误
int c=p[0]; //正确
*p=100; //正确
p[0]=100; //正确
//  *p和p[0]的类型是int类型,不是const int类型
  • 指针常量必须初始化
int* const p; //错误

•无类型指针

Ⅰ、定义无类型指针的格式:void* 变量名;

void* p=NULL;

Ⅱ、无类型指针的特点:

  • *p和p[0]的类型是未知类型,禁止赋值与取值
*p=100; //编译错误 
p[0]=100; //编译错误
  • 禁止对目标数据赋值操作和读取操作,允许指向任何新地址,但又禁止自增加自减
double d = 10;p=&d; //编译正确 
++p; //编译错误
  • 如果要对无类型指针指向的内存操作,必须先强制转化为一种具体类型。
double pc = (double)p; 
*pc=66.4; 
//无类型指针最常用于做形式参数,功能是对任何类型的实参都可以自动匹配

7、const关键字的作用

const是在*符号之前定义的指针变量就是常量指针,如果const在 * 符号之后定义的指针变量就是指针常量。

指针常量:指针里面所存储的内容(内存地址)是常量,不能改变。但是,内存地址所对应的内容是可以通过指针改变的

常量指针:指针指向的是常量,它指向的内容不能发生改变,不能通过指针来修改它指向的内容。但是,指针自身不是常量,它自身的值可以改变,从而指向另一个常量。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值