初识C语言指针(1)

目录

1. 指针的概念

2.内存和地址

3.指针变量和地址

3.1 取地址操作符--(&)

3.2 指针变量

3.3 解引用操作符--(*)

3.4 指针变量所占的空间大小 

4.指针变量类型的意义

4.1 指针的解引⽤

4.2 指针+-整数

4.3  void* 指针

5.const修饰变量

const修饰指针变量

6. 指针运算

6.1 指针+-整数

6.2 指针-指针

6.3 指针的关系运算

 

 


1. 指针的概念

在C语言中,指针用于存储变量的内存地址,通过指针指向变量的内存地址,程序就可以间接访问和操作变量的值。

2.内存和地址

内存是计算机中的一种硬件组件,用于存储正在运行的程序和数据。而地址是指内存中存储单元的编号,用于标识和访问这些存储单元。在计算机中,内存被划分为许多小单元,每个单元都有一个唯一的地址。这些地址通常按照字节为单位进行编号,⼀个字节空间⾥⾯能放8个⽐特(1Byte=8 bit)

在计算机中,将内存单元的编号称为地址 ,在C语言中又给地址取了一个新名字,叫做指针,所以内存单元的编号=地址=指针

3.指针变量和地址

3.1 取地址操作符--(&)

        在C语⾔中创建变量其实就是向内存申请空间存放变量中的值:

我们创建了一个整形变量a, 向内存申请了4个字节的空间大小,用来存放0,并且每个字节都有地址,那我们要怎么样得到a变量的地址呢?这时候我们就要通过取地址操作符 - &取出a的地址:

通过上图我们可以发现 &a 取出的是a所占4个字节中地址较⼩的字节的地址,虽然整型变量占⽤4个字节,但是我们只要知道了第⼀个字节地址,就能够顺藤摸⽠访问到4个字节的数据。

3.2 指针变量

什么是指针变量呢?上面我们通过取地址操作符,将a的地址取出来后,为了方便后续的使用,也是需要存储起来的,那我们就可以将这样的地址存放在指针变量中,所以指针变量也是⼀种变量,这种变量就是⽤来存放地址(指针)的,存放在指针变量中的值都会理解为地址。例如:

int main()
{
	int a = 0;
	int* p = &a;
	return 0;
}

既然指针变量是一种变量,想必也会有变量的类型,从上面的代码中,我们可以这么理解:创建了一个指针变量p用来存放a的地址,而 int *就是指针变量p的类型,* 是在说明p是指针变量,⽽前⾯的 int 是在说明p指向的是整型(int) 类型的对象。

如果有⼀个char类型的变量ch,ch的地址,就应该放在 char *类型的指针变量中,例如:

int main()
{
	char ch = 'a';
	char* pc = &ch;
	return 0;
}

3.3 解引用操作符--(*)

我们拿到了地址(指针),就可以通过地址(指针)找到地址(指针) 指向的对象,这个过程就需要通过解引用操作符去实现:

*pa 的意思就是通过pa中存放的地址,找到指向的空间, *pa其实就是a变量;所以*pa = 20,这个操作符是把a的值改成了20,其实这⾥是把a的修改交给了pa来操作,这样对a的修改,就多了⼀种的途径。

3.4 指针变量所占的空间大小 

指针变量的⼤⼩和类型是⽆关的,只要指针类型的变量,在相同的平台下,⼤⼩都是相同的。

int main()
{
	printf("%zd\n", sizeof(char*));
	printf("%zd\n", sizeof(short*));
	printf("%zd\n", sizeof(int*));
	printf("%zd\n", sizeof(double*));
	return 0;
}

在32位平台下地址是32个bit位,指针变量⼤⼩是4个字节

  

 

64位平台下地址是64个bit位,指针变量⼤⼩是8个字节 

4.指针变量类型的意义

4.1 指针的解引⽤

指针的类型决定了,对指针解引⽤的时候⼀次能操作⼏个字节,⽐如: char* 的指针解引⽤就只能访问⼀个字节,⽽ int* 的指针的解引⽤就能访问四个字节:

对于上图我们就发现 int *类型的指针在解引用的时候,可以访问到4个字节的内容进行修改,而char *类型的指针在解引用的时候,只能访问到1个字节的内容进行修改。

4.2 指针+-整数

指针的类型决定了指针向前或者向后跳过几个字节的大小

int *类型:

char *类型:

4.3  void* 指针

void* 类型是指针类型中一种特殊的类型,可以理解为无具体类型的指针,这种类型的指针可以⽤来接受任意类型地址,但是void* 类型的指针不能直接进 ⾏指针的+-整数和解引⽤的运算。

因为在进行指针+-整数的时候,void*类型的指针无法确定每次加减多少个字节单位,并且在解引用的时候,不能确定访问多少个字节单位的内容。

编译器也会进行报错。 

5.const修饰变量

当使用const修饰变量时,此时的变量就变成了常变量,不能被修改:

但是我们可以通过另一种方式对a进行修改,那就是指针的间接访问 :

但是既然我们既然一开始就不想变量a被改变,所以使用了const进行修饰,但是还能通过指针进行间接访问,这该怎么办呢? 别急,const不仅能修饰普通的变量,还能修饰指针变量。

const修饰指针变量

1.const放在*号的左边:修饰的是指针指向的内容(*pa),表示指针指向的内容(*pa)不能通过指针进行改变了,但是指针变量(pa)本身的值是可以改变的

2.const放在*号的右边:修饰的是指针变量(pa)本⾝,保证了指针变量(pa)本身的值不能修改,但是指针指向的内容(*pa)可以通过指针改变

3.*号两边都放上const: 表示指针变量本身(pa)的值不能被修改,指针指向的内容(*pa)也不能通过指针进行改变了

6. 指针运算

6.1 指针+-整数

在上面我们讲了指针+-运算的用法,现在我们搭配数组一起使用看看:

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int* pa = arr;
	int sz = sizeof(arr) / sizeof(arr[0]);//求数组的元素个数
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", *(pa + i));
	}
	return 0;
}

 我们将arr数组首元素的地址存放在pa中,因为数组中元素的地址是连续存放的,所以此时pa+1就是下标为1的元素的地址,*(pa+1)就是下标为1的元素,带入循环,每次打印的就是arr数组中下标为 的元素。

6.2 指针-指针

指针-指针就是地址-地址,它们得到的结果就是它们之间所存放的元素个数:

 那么我们接下来自己来写一个计算字符串长度的函数:

size_t my_strlen(char* str)
{
	char* s = str;
	while (*str != '\0')
	{
		str++;
	}
	return str - s;
}
int main()
{
	char ch[] = "abcdef";
	size_t len = my_strlen(ch);
	printf("%zd", len);
	return 0;
}

 

 首先我们创建了一个数组存放字符串,实际上字符数组ch中存放的是 a b c d e f \0 ,将ch首元素的地址传给my_strlen,在my_strlen中,我们创建一个char*类型的指针变量str来接收ch首元素的地址,然后将str的值赋给s,我们通过while循环,直到*str=\0时,那么就停止++

最后返回str-s(指针-指针)的值,得到的就是\0和a之间的元素个数,也就是这个字符串中字符的个数。 

6.3 指针的关系运算

指针与指针之间也可以进行大小的比较

例如:

我们直到数组元素的地址是通过下标的增长而递增的,所以我们可以通过地址的比较作为循环的 执行条件,打印出数组的元素个数。

以上就是初识指针1的全部内容,希望大家看完本章内容,能够对指针有一个初步的认识,后续会继续更新指针的更多内容,如有错误欢迎指出,谢谢大家!!!

  • 22
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值