指针定义、指针与数组、指针运算、比较

目录

一、指针相关定义

二、数组与指针

1.数组变量是特殊的指针

2.指针与const

a、所指是const时

b、const转化

c、const数组

三、指针运算

指针+1:

*p++

四、指针比较


一、指针相关定义

符号: *p

定义:指针内存地址,而指针变量是用来存放内存地址的变量。

特点:可对存储数据的变量地址进行操作

性质:不同类型的指针变量所占用的存储单元长度是相同的,而存放数据的变量因数据的类型不同,所占用的存储空间长度也不同。

指针描述了数据在内存中的位置,标示了一个占据存储空间的实体,在这一段空间起始位置的相对距离值。

*是一个单目运算符,用来访问指针的值所表示的地址上的变量

可以做右值读取,也可以做左值写入

int k =*p;(读取)

*p = k+1;(写入)

  • p是一个地址

  • *p是一个值

#include<stdio.h>
void a(int* p);
void b(int i);

int main(void)
{
	int i = 6;
	printf("&i=%p\n", &i);
	int * p;
	p = &i;  //初始化
	*p = 12;
	printf("%p\n", &i);
	a(&i);
	b(i);
    return 0;
}

void a(int* p) 
{
	printf("p = % p\n", p);
	printf("*p=%d\n", *p);
}

void b(int k)
{
	printf("k=%d\n", k);
}

如图:

 可见:当值改变时地址并没有改变

  • p是一个地址,用%p打印

  • *p是一个值,可以通过改变 *p来改变原本 i 的值

注:任何一个*p在没有得到实际变量的地址之前,是不能对其进行赋值的(初始化) 可能不会报错,但是需要注意。


二、数组与指针

1.数组变量是特殊的指针

传入函数的数组成了什么?,函数参数表中的数组实际上是指针。

  • sizeof(a) == sizeof(int*)

数组参数

以下四种函数原型是等价的:

int sum(int *ar, int n);

int sum(int ar[], int n);

int sum(int *, int);

int sum(int [], int);

注:void fun(int n);//这就是函数原型。

    它们的类型并不一样,而是说如果它们在参数表中出现,作为函数原型,它们是等价的。


数组变量本身表达地址

int a[10]; int *p=a; //  直接用数组变量名,无需用&取地址

a == &a[0];  //但是当数组的单元表达的是单个变量,需要用&取地址

[]运算符可以对数组做,也可以对指针做:

p[0] <==> a[0]

*运算符可以对指针做,也可以对数组做:

*a=25;

数组变量是const的指针,所以不能被赋值

int a[ ] <==> int* const a=……


2.指针与const

指针是const,一旦指向一个变量的地址,就不能再指向其他变量

#include<stdio.h>
int main
{
 int * const p = &i; //一旦指向一个变量的地址,不能再指向其他变量

 *p = 26; //ok

  p++;//wrong 

}

a、所指是const时

不能通过该指针去修改该变量,原变量i仍然可以修改

#include<stdio.h>
int main
{
 int const *p = &i;//不能通过该指针去修改该变量,原变量i仍然可以修改

 *p = 26;//error!
 
 i = 26;//ok 因为i不是const

 p = &j; // ok   

}

b、const转化

总是可以把一个非const的值转换成const的值

#include<stdio.h>
int main
{
int a = 15; f(&a); // OK 
const int b = a; f(&b); // OK 
b = a+1;  //Error! const不能再改变
}

运用const转化保护数组值不被函数破坏

如:

int sum(const int a[], int length);

又因为把数组传入函数时传递的是地址,所以那个函数内部可以修改数组的值


c、const数组

初始化

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

  • 数组变量是const的指针,这里的const表面数组的每个单元都是const int
  • 所以必须通过初始化进行赋值

三、指针运算

指针+1:

#include<stdio.h>
int main(void)
{
	char ac[] = { 0,1,2,3,4,5 };
	char* p = ac;
	printf("p=%p\n", p);
	printf("p+1=%p\n", p + 1);

	int ai[] = { 0,1,2,3,4,5};
    int* q = ai;
	printf("q = % p\n", q);
	printf("q+1=%p\n", q + 1);

}

运行如下:

  •  可见,是加上一个sizeof指针类型,如char一个单元占据1字节,int一个单元占据4字节

*p++

  • 取出p所在的位置,并把把p移到下一个位置去
  • *的优先级虽然高,但是没有+高   
  • 常用于数组的连续空间操作
  • 在某些cpu上,可以直接被翻译成一条汇编指令

注:*属于单目运算符, 运算*(p+1)时 ,需要用上小括号,否则先运算+


四、指针比较

  • <,<=,==,>,>=,!= 都可以对指针做
  • 比较它们在内存中的地址
  • 数组中的单元的地址肯定是线性递增的

注:指针不可以做乘除,这没有任何意义


0地址

  • 现代操作系统都是多进程操作系统,它的基本管理单元是进程。
  • 操作系统会给进程分配一个虚拟的地址空间,所有的程序在运行时都以为自己具有从0开始的一片连续空间。

但是指针不应该具有0值。

我们可以用0地址来表示特殊的事情:

  • 返回的指针是无效的
  • 指针没有被真正初始化(先初始化为0)

Null是一个预定定义的符号,表示0地址。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值