C语言中指针的运用

目录

指针概述

指针运算

指针与数组

指针与二维数组

字符指针与字符串



指针概述

概念:在C语言中,指针的实质就是地址,专门用来存放地址的变量,称为指针变量。

此外,还需要注意的是,指针的存储类型是指针变量本身的存储类型。
指针声明时,指定的数据类型不是指针变量本身的数据类型,而是指针目标的数据类型。简称为指针的数据类型。

 指针变量的形式一般是:

//指针在声明的同时,也可以被赋予初值,称为指针的初始化
// 一般形式是:<存储类型>  <数据类型>  *<指针变量名> = <地址量> ; 
int  x,  *px=&x;
//在上面语句中,把变量x的地址作为初值赋予了刚说明的int型指针px。
int x = 3;   //int x; x = 3;
int *px = &x; //int *  px; px = &x;

这里,指针px指向变量x,指针px中存放的是变量x的空间地址。

引入指针要注意程序中的px、*px 和 &px 三种表示方法的不同意义。设px为一个指针,则:
px  — 指针变量, 它的内容是地址量
*px — 指针所指向的对象, 它的内容是数据
&px — 指针变量占用的存储区域的地址,是个常量

指针运算

在c语言中,对指针进行运算操作,要先明白几个关键点:

  1. 指针运算是以指针变量所存放的地址量作为运算量而进行的运算
  2. 指针运算的实质就是地址的计算
  3. 指针运算的种类是有限的,它只能进行赋值运算、算术运算和关系运算

指针的算术运算见下表:

注意:

  • 不同数据类型的两个指针实行加减整数运算是无意义的
  • px+n表示的实际位置的地址量是:

     (px) + sizeof(px的类型) * n

  • px-n表示的实际位置的地址量是:

     (px) - sizeof(px的类型) * n

  •  两指针相减运算

    px-py 运算的结果是两指针指向的地址位置之间相隔数据的个数,是一个整数值,表示两   指针之间相隔数据的个数,而不是px-py的持有的地址值相减。

  1 #include <stdio.h>
  2 
  3 int main(int argc, char *argv[])
  4 {
  5     int a[5] = {4, 8, 1, 2, 7};
  6     int *p, * q;
  7 
  8     p = a; //&a[0];
  9     q = &a[3];
 10 
 11     printf("%d %d\n", *p, *q);
 12     printf("%d\n", q-p);    //a[0]到a[3]有三个元素
 13     
 14     return 0;
 15 }   
 16 

结果:
4  2
3

 指针与数组

在C语言中,指向数组的指针所指向的空间地址是数组在内存中的起始地址,一维数组的数组名为一维数组的指针(起始地址)

//例如:
double   x[8];
double * px = x;

x为x数组的起始地址

设指针变量px的地址值等于数组指针x(即指针变量px指向数组的首元数),则:
x[i] 、*(px+i)、*(x+i) 和px[i]具有完全相同的功能:访问数组第i+1个数组元素

  1 #include <stdio.h>
  2 
  3 int main(int argc, char *argv[])
  4 {
  5     int x[5] = {4, 8, 1, 2, 7};
  6     int *px;
  7 
  8     px = x; //&x[0];
  9     
 10       //依次打印x[i] 、*(px+i)、*(x+i) 和px[i]
 11     printf("%d- %d- %d - %d\n", x[3], *(px+3), *(x+3), px[3]);
 12     return 0;
 13 }
 14 结果:2- 2- 2- 2
    

~                                                                               
~            

注意:

  1. 指针变量和数组在访问数组中元素时,一定条件下其使用方法具有相同的形式,因为指针变量和数组名都是地址量
  2. 但指针变量和数组的指针(或叫数组名)在本质上不同,指针变量是地址变量,而数组的指针是地址常量例如指针px做为地址变量,可以做自增自减操作px++、px--,但是x作为地址常量,则不能做自增自减操作,编译器会报错

指针与二维数组

多维数组就是具有两个或两个以上下标的数组
在C语言中,二维数组的元素连续存储,按行优先存

我们先声明一个二维数组:

int a[3][2]={{1,2},{3,4},{5,6}}

 二维数组a中包含了三个元素:a[0]、a[1]、a[2].其中每个元素又是一个含有两个元素的一维数组。例如:一维数组a[0],含有两个元素a[0][0]、a[0][1].

先明白二维数组中几个关键点:

在二维数组中:
int a[3][2] = {{1, 2}, {3, 4}, {5, 6}}; 
int (*p)[2];  //这里定义一个行指针,实际上就是一个指针数组,每个数组元素都是一个指针
p = a;       //将行指针p指向二维数组a


a; //代表数组首行地址,一般用a[0][0]的地址表示

&a; //代表整个数组的地址,一般用a[0][0]地址表示

*p; //代表数组a首元素地址也就是a[0]或者&a[0][0]

*(p+i); //代表了第i行首元素的地址,*a是i=0的情况

*(p+i)+j; //代表了第i行j个元素的地址

**a; //代表a的首元素的值也就是a[0][0]

*(*(a+i)+j); //代表了第i行第j个元素
二维数组demo
  2 #include <stdio.h>
  3 
  4 int main(int argc, char *argv[])
  5 {
  6     int a[3][2] = {{1, 2}, {3, 4}, {5, 6}};
  7 
  8     int (*p)[2];  //这里定义一个行指针
  9     int i, j;
 10 
 11     p = a;       //将行指针p指向二维数组a
 12 
 13     //分别对a、p做算术加运算,打印a+1、p+1、a[1][0]、p[1][0],地址量一致
 14     printf("%p %p %p\n", a, a+1,&a[1][0]);
 15     printf("%p %p %p\n", p, p+1,&p[1][0]);
 16 
 17 
 18     printf("依次遍历: a[i][j], p[i][j], *(*(a + i)+j), *(*(p + i) + j)\n");
 19     for (i = 0; i < 3; i++) {
 20         for (j = 0; j < 2; j++)
 21 
 22           printf("%d-- %d-- %d-- %d ", a[i][j], p[i][j], *(*(a + i)+j), *(*(p + i) + j));
 23         puts("");
 24     }
 25 
 26 
 27     return 0;
 28 }
 29 

打印结果:
0xbfb3f1d8 0xbfb3f1e0 0xbfb3f1e0
0xbfb3f1d8 0xbfb3f1e0 0xbfb3f1e0
依次遍历: a[i][j], p[i][j], *(*(a + i)+j), *(*(p + i) + j)
1-- 1-- 1-- 1 2-- 2-- 2-- 2 
3-- 3-- 3-- 3 4-- 4-- 4-- 4 
5-- 5-- 5-- 5 6-- 6-- 6-- 6 
~          

 字符指针与字符串

初始化字符指针是把内存中字符串的首地址赋予指针,并不是把该字符串复制到指针中

  1 //字符指针
  2 #include<stdio.h>
  3 int main()
  4 {
  5      char  str[] = "Hello World";
  6      char  *p = str;
  7      printf("%s\n",p);
  8      return 0;
  9 }

  结果:Hello World

需要注意的是

在C编程中,当一个字符指针指向一个字符串常量时,不能修改指针指向的对象的值:

  char  *  p = “Hello World”; 
  *p = ‘h’;    //  错误, 字符串常量不能修改
//字符串常量
#include<stdio.h>
#include<ctype.h>
int main()
{
	//这里声明两个指向字符串常量的字符指针p1、p2
	char* p1 = "hello world";
	char* p2 = "hello world";

	printf("&p1= %p  p1指向的地址: %p p1指向的值: %s\n",&p1,p1,p1);
	
	printf("&p2= %p  p2指向的地址: %p p2指向的值: %s\n",&p2,p2,p2);
	return 0;

}
结果:
&p1= 0xbfed0438  p1指向的地址: 0x8048520 p1指向的值: hello world
&p2= 0xbfed043c  p2指向的地址: 0x8048520 p2指向的值: hello world

不能修改的原因在于,不同于我们在程序中,声明一个字符串数组(例如:char* str[]),计算机会将声明的变量的存储空间放在了栈里面,进行动态管理;

不同于字符串数组,字符串常量,就像全局变量、static存储类型的声明一样,数据是存储在一个固定的静态存储区中的,静态存储区里面的数据一般是不能改变的,而且会在程序的执行结束后, 才会释放静态存储区里面的数据。例子中,两个字符指针p1、p2都是指向同一个地址

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个指针的应用习题及注释: ```c #include <stdio.h> int main() { int x = 10; // 定义整型变量 x 并赋值为 10 int *p = &x; // 定义指针变量 p 并指向 x 的地址 int y = 5; // 定义另一个整型变量 y 并赋值为 5 printf("x 的值为 %d\n", x); // 输出 x 的值 printf("p 的值为 %p\n", p); // 输出 p 的值,即 x 的地址 printf("*p 的值为 %d\n", *p); // 输出 p 所指向的值,即 x 的值 p = &y; // 使指针变量 p 指向 y 的地址 printf("y 的值为 %d\n", y); // 输出 y 的值 printf("p 的值为 %p\n", p); // 输出 p 的值,即 y 的地址 printf("*p 的值为 %d\n", *p); // 输出 p 所指向的值,即 y 的值 *p = 8; // 通过指针变量 p 修改 y 的值为 8 printf("y 的值为 %d\n", y); // 再次输出 y 的值,应为 8 return 0; } ``` 注释: - 第 3 行:定义整型变量 x 并赋值为 10。 - 第 4 行:定义指针变量 p。 - 第 5 行:使指针变量 p 指向 x 的地址。 - 第 6 行:定义另一个整型变量 y 并赋值为 5。 - 第 8 行:输出 x 的值。 - 第 9 行:输出 p 的值,即 x 的地址。这里使用了 %p 作为格式控制符。 - 第 10 行:输出 p 所指向的值,即 x 的值。 - 第 12 行:使指针变量 p 指向 y 的地址。 - 第 14 行:输出 y 的值。 - 第 15 行:输出 p 的值,即 y 的地址。 - 第 16 行:输出 p 所指向的值,即 y 的值。 - 第 18 行:通过指针变量 p 修改 y 的值为 8。 - 第 20 行:再次输出 y 的值,应为 8。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值