C语言(七)—— 指针

1.指针

地址:按字节为单位进行编号;
指针:就是地址
指针变量:用来保存地址的变量;
指针的目标变量:指针指向的变量;

1.1指针的一般形式

《存储类型》《数据类型》 * 《指针变量名》;
存储类型:存储类型和指针变量自身有关,和指针的目标变量无关;
数据类型:由指针的目标变量来确定;
指针变量名:保存目标变量的地址;
eg:
int var ;
int *p;//一个可以指向整型地址的指针变量;
p = &var; // p指向了var
p ---> 指针变量
&var --> 指针
var --> 指针的目标变量;
//(在不影响理解的情况下,地址、指针、指针变量统称为指针)

1.2*和&运算符

&: 在一个变量的基础上取地址可以得到变量的地址;
*:在地址的基础上取*可以得到这个地址上的内容;
& * 互为逆运算

2.指针的初始化

《存储类型》《数据类型》 * 《指针变量名》 = <地址量>;
eg:
int var = 10;
int *p = &var;
&var == p == &(*p)
var == *p == *(&var)
&p: 表示指针变量自身的地址,和目标变量无关;

3.指针的大小

指针所占的字节数和操作系统有关,和数据类型没有关系;
32位 指针变量占4字节;
64位 指针变量占8字节;

4. 空指针和野指针

空指针:是指指针变量的内容为零的状态;
int *p = NULL;
野指针:一个没有固定指向的指针;要避免野指针的出现;

5.指针的运算

5.1指针的算术运算

+ - ++ --
p + 1 --> 表示指针变量向地址值大的方向偏移一个单位
p++
++p
p-1 --> 表示指针变量向地址值小的方向偏移一个单位
p--
--p
p+q //error
p - q --> 表示两个指针之间相差几个单位
指针偏移的实际地址量:
p +/- n * (sizeof(数据类型))

5.2指针的关系运算

>   <       ==      !=       >=       <=
在比较的时候要保证指针的类型要一样;

5.3  指针的赋值运算

1.将一个变量的地址赋值给一个具有相同类型的指针变量;
eg:
char ch;
char *p;
p = &ch;
2.将一个指针变量赋值给一个具有相同类型的指针;
char *p = &ch;
char *q = p; //p 和 q 都指向ch
3.将一个数组的首地址赋值给一个具有相同类型的指针变量;
int arr[5] = {0};
int *p = arr; //p指向了数组的首地址

6.指针和一维数组的关系

int arr[32] = {0};
int *p = arr;
//数组第i个元素的地址

p + i == &arr[i] == arr + i
//数组的第i个元素
arr[i] == *(p+i) == *(&arr[i]) == *(&p[i]) == p[i]
    ==*(arr+i)
//arr++ // error
p++ //表示p指向第二个元素的地址;

7.指针和字符串

当一个指针要指向字符串的时候,字符串一个有一个存储空间来保存
    将字符串的首地址赋值个指针变量

 eg:
    char buf[] = "hello world" ;
	char * p = buf;
g:
char buf[32] = {0};
char *p = buf;
// strcpy(p, "hello world");
scanf("%s", p);
//将字符串存储到p指向的buf空间中;
eg:
/*
* ***** error eg***************
char *p;
scanf("%s", p);
//相当于将输入的字符串存储到一片没有申请的空间中
//应该让p先指向一片空间
puts(p);*/
char buf[32] = {0};
char *p = buf;
scanf("%s", p);
2.一个指针变量初始化为字符串常量时,
用指针来访问字符串的时候只允许读不允许修改;
eg:
char *p = "hello";
*p = 'H'; //error
//相当于指针p指向字符串常量"hello"的首地址, *p == 'h';
//这个字符串保存在静态数据区的常量区,不允许修改只允许读
   

8.二级指针

一个存储指针的指针;
eg:
int var = 10;
int *p = &var;
int **q = &p;
q == &p;
*q == p == &var;
**q == *p == var;
int var1;
*q = &var1;
//通过指针修改目标的值(p的值)

9.指针和二维数组

eg:
用一级指针访问二维数组;
二维数组的理解:
int arr[2][3];
//可以看成是一个由arr[0] 和 arr[1] 两个一维数组组成;
arr[0] == *(arr + 0) //数组名 +下标 表示每个元素的地址
arr[1] == *(arr + 0)
arr[0] 是第一个一维数组:
元素: 数组名[下标] *(数组名 + 下标)
arr[0][0]==*(arr[0] + 0)== *(*(arr + 0)+0)==(*
(arr+0))[0]
arr[0][1]==*(arr[0]+1)==*(*(arr+0)+1)==(*(arr+0))[1];
arr[0][2]==*(arr[0]+2)== *(*(arr+0)+2)==(*(arr+0))
[2];

总结:

arr[i][j] == *(arr[i]+j) == *(*(arr+i)+j) == (*(arr+i))[j];

10.行指针

二维数组名叫做行地址,二维数组名加一表示偏移一行的元素;
注意:
二维数组不能用二级指针指向,数据类型不一样;
二维数组可以被行指针指向;
行指针的一般形式:
<存储类型> <数据类型> (*指针变量名)[列数];
eg:
int arr[3][2] = {0};
int (*p)[2] = arr;
第i行的第j列的元素:
arr[i][j] == *(arr[i]+j) == *(*(arr+i)+j)
== (*(arr+i))[j]
== p[i][j] == *(p[i]+j) == **(p+i) + j)
== (*(p+i))[j]

11.指针数组

指针数组本质是数组,由若干个相同类型的指针变量组成的集合;
一般形式:
<存储类型> <数据类型> * <指针数组名>[数组的元素个数];
eg:
int arr[3][2];
int *parr[3] = {arr[0], arr[1], arr[2]}
每个元素 arr[i][j]:
*(*(parr + i) + j)
parr: 数组名,地址常量;
parr[i] 表示每个指针变量,占8字节;
指针数组的大小:
8 * 数组元素个数; //64位
访问指针数组可以用二级指针来访问;
eg:
int **pp = parr;
arr[i][j] == *(*(parr + i) + j) = *(*(pp + i) + j);

12.const

const int var;
const 修饰变量,让变量常量化;
const 修饰的局部变量可以通过指针间接修改;
eg1:
1.不能通过指针修改目标的值,但可以修改指针的指向;
int var = 10, var2 = 20;
const int *p = &var; //int const *p = &var;
p = &var2; //true
// *p = 100; //false
2. 不能修改指针的指向,但可以通过指针修改目标的值;
int var = 10, var2 = 20;
int * const p = &var; //必须初始化
//p = &var2; //false
*p = 100;
3.既不能修改指针的指向,也不能通过指针修改目标的值;
int var = 10, var2 = 20;
//int const * const p = &var;
const int * const p = &var;
//p = &var2; //false
// *p = 100; //false

3.void指针

一般形式为:
	void *<指针变量名称> ;
	对于void型的指针变量,实际使用时,一般需通过强制类型转换才能
	使void型指针变量得到具体变量或数组地址。在没有强制类型转换之前,
	void型指针变量不能进行任何指针的算术运算。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值