指针知识框架(详解)

本文为C语言学习过程中关于指针的笔记。根据书籍和程序题并参考网络上的博客回答,撰写的感悟和收获。
文章参考:
C语言解惑指针、数组、函数和多文件编程(作者刘振安刘燕君,机械工业出版社)

一、对指针使用const限定符

1.指向常量的指针

const int  y=66;
const int p=&y; //此时y和p都不能做为左值,但可以作为右值。

使指针指向一个不可修改的常量,即p是常量。但是可以通过修改p指向的地址,改变p的值。
例如:

1
2
3
4
5
6
7
8
9
 const int y=66;
int x=50;
const int * p =&y;
printf("%d,%d,%p\n",y,*p,p);
p=&x;
printf("%d,%d,%p\n",x,*p,p);
/*输出结果为:
66,66,000000000062FE14
50,50,000000000062FE10*/

由指向y改为指向x,*p被覆盖。

2.指向常量的指针指向非常量

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
int main()
{
int x=55 ;//变量x能作为左值和右值
const int y=88;//常量y不能作为左值,但可以作为右值
const int *p;//声明指向常量的指针
int *p1 ;//声明指针
p=&y ;//用常量初始化指向常量的指针,*p不能作为左值
printf ("%d ",*p) ;
p=&x;//p作为左值,使常量指针改为指向变量x,*p不能作为左值
printf("%d ",*p) ;
x=128 ;//用x作为左值间接改变*p的值,使*p=x=128
printf("%d ", *p) ;
p1=(int*)&y;
printf("%d\n", *p1) ;
return 0;
}

示例中指向常量的指针p指向变量x,仅限制直接使用p作为左值,但可以通过直接修改x的值改变p的值。同时也与使用非常量指针一样,也可以直接使用“&”改变常量指针的指向,显然也改变了*p的值。

【注】常量只能由指向常量的指针(即const voidp)指向,否则必须进行强制转换,将常量强制转换为相应的指针类型。如示例:p1=(int)&y;

3.常量指针

限定符const放在*号右边,是指针本身成为一个const指针。声明常量时必须进行初始化,即指针变量p存储的为常量地址。

例如:int x=45;
int * const p=&x//p始终指向x的地址。但可以修改x地址内存的值,x=123和*p=123;但p指向的地址不能改变

4.指向常量的常量指针

即指针和指向的对象都不能改动的“指向常量的常量指针”。p和p都是常量。限制了“&”和“”运算符,很少使用。

5.void指针

void类型不能声明变量,但可以声明void类型的指针,而void型指针可以指向任何类型的变量。

1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>
int main()
{
int x=256, y=386,*p=&x;
void*vp=&x;
printf("%d,%d,%d\n",vp,p,x);
vp=&y;
p=(int*)vp;//虽然void指针指向整型变量对象x,但不能使用*vp应用整型对象的值。要引用这个值,必须强制将void指针赋值给与值相对应的指针类型。
printf("%d,%d,%d\n",vp,p,*p);
return 0;
}

【注】但奇怪的是,测试时发现p=(int*)vp不加(int*)也可以正常运行。

小结

const放在的右边(void * const p),修饰的是指针(即指针变量p指向的地址)不可改变。
const放在前端(const void * p),修饰的是指向的对象(指针变量p存储的地址的值),即
p是常量

二、指针与数组

1.数组与指针的关系

指向数组的指针实际上指的是能够指向数组众人一个元素的指针。

int a[5];
int *pa=&a[0];//等同于int *pa;
           pa=a;

数组名和指针的区别:指针是变量:pa=a或pa是有意义的;
      数组名是指针常量:a=pa、a
、pa=&a(a本身就是地址,无法对地址取地址)是非法操作。
假设指针现在指向a[0],则数组的第i个(下标为i)元素可表示为a[i]或*(pa+i),还可使用带下标的指针pa,即pa[i]和*(pa+i)的含义一样。若将a[i]的值修改,下列语句等价。

a[i]=123; *(a+4)=123; *(pa+4)=123; pa[4]=123;

指针与数组元素的关系

下标 数组名 指针 指针下标 四者的逻辑关系
a[0] a pa pa[0] a[0]*a*pa==pa[0]
a[1] a+1 pa+1 pa[1] a[1]*(a+1)*(pa+1)==pa[1]
a[2] a+2 pa+2 pa[2] a[2]*(a+2)*(pa+2)==pa[2]

2.指针数组和数组指针

数组的指针:是一个指针,什么样的指针呢?指向数组的指针。
指针的数组:是一个数组,什么样的数组呢?装着指针的数组。
本质是的后面是类型。
然后,需要明确一个优先级顺序:()>[]>*,所以:
(*p)[n]:根据优先级,先看括号内,则p是一个指针,这个指针指向一个一维数组,数组长度为n,这是“数组的指针”,即数组指针;
p[n]:根据优先级,先看[],则p是一个数组,再结合,这个数组的元素是指针类型,共n个元素,这是“指针的数组”,即指针数组。
根据上面两个分析,可以看出,p是什么,则词组的中心词就是什么,即数组“指针”和指针“数组”。
————数组指针和指针数组_mick_hu的博客-CSDN博客_数组指针和指针数组原文地址

3. c语言优先级

C语言运算符优先级(超详细)_embed_huang的博客-CSDN博客_c语言运算符优先级构成一系列表达式(六个左右),然后分析并打印输出他的结果原文地址