C语言精要总结-指针系列(二)

简介:   此文为指针系列第二篇: C语言精要总结-指针系列(一) C语言精要总结-指针系列(二) 指针运算 前面提到过指针的解引用运算,除此之外,指针还能进行部分算数运算、关系运算 指针能进行的有意义的算术运算包括加减法运算,但不包括乘除运算。

 

此文为指针系列第二篇:

C语言精要总结-指针系列(一)

C语言精要总结-指针系列(二)

指针运算

前面提到过指针的解引用运算,除此之外,指针还能进行部分算数运算、关系运算

指针能进行的有意义的算术运算包括加减法运算,但不包括乘除运算。并且运算存在诸多限制。

加法运算

指针加法运算只适合指针与整数,不能用在指针与指针。

指针加上或者减去一个整数n,是存储的地址值加上或者减去n*指针指向类型的空间大小。也就是

结果指针 = 指针 ±  n * 指针指向类型空间大小。

例如int类型的整数指针+1,运算结果依然是一个整型指针,其存储的地址值为原指针值+1*4,这是因为整型变量占用4个字节的空间。这个计算结果,恰好在当前指针指向基础上,向下偏移指向下一个相同类型的空间。如下图

 

指针与整数的加减法一般用在迭代连续的内存空间-数组,如果运算得到的指针指向第一个元素之前或者最后一个元素之后,可能会产生非法读写内存中断,就像引用一个未初始化的指针一样不可预知。

指针除了可以与整数做加减运算,连个指针之间还可以做减法运算(不能做加法运算)且必须是同类型的指针。运算结果为两个指针指向地址之间,可以存放多少此类型的变量数(或其相反数),类型为ptrdiif_t类型(一种有符号整数类型)。

1 int * p1 = (int *) 0x100;
2 int * p2 = (int *) 0x10c;
3 printf("p2-p1 : %d\n",p1 - p2); // -3

如上程序将输出-3,也如上图所示,这3个空间存放着 10、80、6三个整型变量。

指针与指针相减,一般也用在连续地址空间-数组中。此时两个指针相减跟下标索引相减是等价的。

1 int arr[5] ;
2 printf("%d\n",&arr[4] - &arr[0] == 4 - 0); // 1

常量指针与指针常量

常量指针表示通过此指针,不能修改其指向的内存区域的内容,指针本身的值是可以修改为指向另一个变量,虽然可以修改指向另一个变量,但是依然不允许修改指向变量里的内容。常量指针一般用在函数一些函数参数中,以只读的方式传递函数参数。这里说明一点C语言除了宏定义常量和枚举之外,是不能定义普通常量的,只可用const定义只读变量,而常量指针指向的是就是一个只读变量。只读变量是不能修改的变量。

1 const int readOnlyVar = 10;
2 int * pROVar = (int *) & readOnlyVar;
3 * pROVar = 11;
4 printf("%d\n",readOnlyVar);

指针常量表示指针本身的内容不可变(指向不可变),因此,定义指针常量时必须同时初始化一个地址值。

定义指针常量和定义常量指针的方式区别在于const关键字的位置

int const * p1 ;
const int * p2 ;
int * const p3 = NULL;
const int * const p4 = NULL;

以*号为界限,看cosnt修饰的是谁,如果修饰的是类型关键字,表示指向常量类型——常量指针,如果修饰的是指针标识符,表示指针常量。显然p1、p2是常量指针,p3是指针常量,p4既是常量指针,又是指针常量。

指针数组

指针数组指元素由指针组成的数组,一般用在存储字符串组,例如下面的程序

 1 char * options[5] = {
 2     "--list",
 3     "--prefix",
 4     "--with"
 5 };
 6 for (i = 0 ; i < 5 ;i ++)
 7 {
 8     if (NULL != options[i]){
 9         printf("%s\n",options[i]);
10     }
11 }

此时指针数组前三个成员指向静态区的三个字符串常量,而后两个指针被默认初始化为0(NULL)

C语言中出现的字符串字面量,实际是存储在静态数据区的字符串常量。当一个字符串出现在C语言表达式中,其实际值是一个指针常量。如下面声明一个指针常量的代码

char * str = "hello";

可以用另一段代码来描述,即先在某处为字符串分配空间,记录指向第一个字符的一个指针常量,并将字符拷贝进去。代码如下

char * const strBuff = (char * ) malloc (6);
strcpy(strBuff,"hello");
char * str = strBuff;
free(strBuff);

既然明确字符串常量在代码中实际是一个指针常量,因此其也可以参与运算。代码如下

printf("%c\n",* "hello");   //  h
printf("%s\n", "hello" + 1);//  ello

常量指针“hello”+1后得到一个新的指针,按指针运算的规则将指向下一个e,所以以字符串形式输出ello

除此之外指针输在还用在处理许多多维数组的地方,这在后续的章节中会提到。

常量指针数组与指针常量数组

常量指针数组表示元素都指向常量的数组。定义方式如下

1 const char * options[5] = {
2     "--list",
3     "--prefix",
4     "--with"
5 };

当然,这里的例子,const加与不加没太大区别,因为即便不加const关键字,options中的每一个元素依然是指向一个字符串常量,是不能修改的。例如要将“--list”中的第2个‘-’换成'+'号,下面的代码是行不通的,方法只有让指针指向一个全新的字符串常量(因为是常量指针,所以指针本身的内容可以修改)

* (options[0] + 1) = '+';

加上const的好处是,让编译器或者IDE工具在运行之前便告知你此类代码存在的问题。关于字符串常量,下面的异常代码可能更易懂一些

char * str = "hello";
*(str + 3) = 'w';

指针常量数组表示每个指针元素都是不可修改的(指向固定了),但是其指向内容,视情况是可以修改的。

1 char * const options[5] = {
2     "--list",
3     "--prefix",
4     "--with"
5 };

当然,因为字符串常量的缘故,上面的代码定义了一个指针元素、指针元素指向区域内都不可变的指针数组。例如,像下面的代码都是非法的

1 options[0] = tmpStr; // 修改指针指向新的字符串常量
2 *(options[0]) = '+'; // 修改第一个元素指向区域的内容

下一系列将用一两个复杂的案例详细讲解指针与数组的关系。

目录
相关文章
|
3月前
|
C语言
【c语言】指针就该这么学(1)
本文详细介绍了C语言中的指针概念及其基本操作。首先通过生活中的例子解释了指针的概念,即内存地址。接着,文章逐步讲解了指针变量的定义、取地址操作符`&`、解引用操作符`*`、指针变量的大小以及不同类型的指针变量的意义。此外,还介绍了`const`修饰符在指针中的应用,指针的运算(包括指针加减整数、指针相减和指针的大小比较),以及野指针的概念和如何规避野指针。最后,通过具体的代码示例帮助读者更好地理解和掌握指针的使用方法。
62 0
|
30天前
|
存储 NoSQL 编译器
【C语言】指针的神秘探险:从入门到精通的奇幻之旅 !
指针是一个变量,它存储另一个变量的内存地址。换句话说,指针“指向”存储在内存中的某个数据。
84 3
【C语言】指针的神秘探险:从入门到精通的奇幻之旅 !
|
30天前
|
存储 编译器 C语言
【C语言】指针大小知多少 ?一场探寻C语言深处的冒险 !
在C语言中,指针的大小(即指针变量占用的内存大小)是由计算机的体系结构(例如32位还是64位)和编译器决定的。
51 9
|
30天前
|
安全 程序员 C语言
【C语言】指针的爱恨纠葛:常量指针vs指向常量的指针
在C语言中,“常量指针”和“指向常量的指针”是两个重要的指针概念。它们在控制指针的行为和数据的可修改性方面发挥着关键作用。理解这两个概念有助于编写更安全、有效的代码。本文将深入探讨这两个概念,包括定义、语法、实际应用、复杂示例、最佳实践以及常见问题。
44 7
|
2月前
|
存储 C语言
C语言如何使用结构体和指针来操作动态分配的内存
在C语言中,通过定义结构体并使用指向该结构体的指针,可以对动态分配的内存进行操作。首先利用 `malloc` 或 `calloc` 分配内存,然后通过指针访问和修改结构体成员,最后用 `free` 释放内存,实现资源的有效管理。
147 13
|
2月前
|
存储 程序员 编译器
C 语言数组与指针的深度剖析与应用
在C语言中,数组与指针是核心概念,二者既独立又紧密相连。数组是在连续内存中存储相同类型数据的结构,而指针则存储内存地址,二者结合可在数据处理、函数传参等方面发挥巨大作用。掌握它们的特性和关系,对于优化程序性能、灵活处理数据结构至关重要。
|
2月前
|
算法 C语言
C语言中的文件操作技巧,涵盖文件的打开与关闭、读取与写入、文件指针移动及注意事项
本文深入讲解了C语言中的文件操作技巧,涵盖文件的打开与关闭、读取与写入、文件指针移动及注意事项,通过实例演示了文件操作的基本流程,帮助读者掌握这一重要技能,提升程序开发能力。
121 3
|
2月前
|
存储 C语言 开发者
C 语言指针与内存管理
C语言中的指针与内存管理是编程的核心概念。指针用于存储变量的内存地址,实现数据的间接访问和操作;内存管理涉及动态分配(如malloc、free函数)和释放内存,确保程序高效运行并避免内存泄漏。掌握这两者对于编写高质量的C语言程序至关重要。
62 11
|
2月前
|
存储 算法 程序员
C 语言指针详解 —— 内存操控的魔法棒
《C 语言指针详解》深入浅出地讲解了指针的概念、使用方法及其在内存操作中的重要作用,被誉为程序员手中的“内存操控魔法棒”。本书适合C语言初学者及希望深化理解指针机制的开发者阅读。
|
2月前
|
程序员 C语言
C语言中的指针既强大又具挑战性,它像一把钥匙,开启程序世界的隐秘之门
C语言中的指针既强大又具挑战性,它像一把钥匙,开启程序世界的隐秘之门。本文深入探讨了指针的基本概念、声明方式、动态内存分配、函数参数传递、指针运算及与数组和函数的关系,强调了正确使用指针的重要性,并鼓励读者通过实践掌握这一关键技能。
44 1