C语言进阶教程(再论指针和数组(2))

举报
yd_274589494 发表于 2023/10/30 10:10:39 2023/10/30
【摘要】 @TOC 前言本篇文章我们继续讲解指针和数组,因为指针和数组对于刚刚学习C语言或者是学习了不久C语言的同学都会造成一些困扰,所以这里多用几篇文章来帮助大家理解。 一、指针的加1减1运算指针的加1减1运算是指针进行后移或前移一个元素的操作。对指针进行加减操作时,指针的值会根据指针所指向的数据类型的大小进行相应的增加或减少。具体来说,假设 ptr 是一个指向某种数据类型(如整数、字符等)的指针,...

@TOC


前言

本篇文章我们继续讲解指针和数组,因为指针和数组对于刚刚学习C语言或者是学习了不久C语言的同学都会造成一些困扰,所以这里多用几篇文章来帮助大家理解。

一、指针的加1减1运算

指针的加1减1运算是指针进行后移或前移一个元素的操作。对指针进行加减操作时,指针的值会根据指针所指向的数据类型的大小进行相应的增加或减少。

具体来说,假设 ptr 是一个指向某种数据类型(如整数、字符等)的指针,那么 ptr + 1 就会将指针的值增加一个元素大小的偏移量,使其指向下一个元素。相应地,ptr - 1 将指针的值减少一个元素大小的偏移量,使其指向上一个元素。

例如,考虑一个整型指针的例子:

int arr[5] = {1, 2, 3, 4, 5};
int* ptr = arr;

printf("%p\n", ptr);       // 输出 arr 的地址
printf("%p\n", ptr + 1);   // 输出 arr 的下一个元素的地址
printf("%p\n", ptr - 1);   // 输出 arr 的上一个元素的地址

输出结果:

0x7ffeed06b3b0
0x7ffeed06b3b4
0x7ffeed06b3ac

在这个例子中,ptr 指向数组 arr 的第一个元素。通过 ptr + 1,指针的值增加了一个整型数据的大小(通常是4个字节)的偏移量,指向了 arr 的下一个元素。相反,通过 ptr - 1,指针的值减少了一个整型数据的大小的偏移量,指向了 arr 的上一个元素。

需要注意的是,指针进行加减运算时,移动的距离取决于指针所指向的数据类型的大小。这保证了指针正确地指向连续的内存位置。此外,指针运算也受限于有效的内存边界,不应越界访问或指向无效的内存位置。

二、指针的减法运算

指针的减法运算用于计算两个指针之间的偏移量(以元素个数为单位)。它可用于确定两个指针之间的元素数量或计算指针相对于基准指针的偏移量。

假设我们有两个指针 ptr1 和 ptr2,它们指向同一类型的元素。可以使用减法运算符 - 计算它们之间的差值,并得到它们之间元素的个数。
例如,考虑以下示例,其中 ptr1 和 ptr2 是指向整型数组中的不同元素的指针:

int arr[5] = {1, 2, 3, 4, 5};
int* ptr1 = &arr[2];
int* ptr2 = &arr[0];

ptrdiff_t diff = ptr1 - ptr2;
printf("Elements between ptr1 and ptr2: %td\n", diff);

输出结果:

Elements between ptr1 and ptr2: 2

在这个例子中,ptr1 指向数组 arr 的第3个元素(值为3),而 ptr2 指向数组 arr 的第1个元素(值为1)。通过 ptr1 - ptr2 计算两个指针之间的偏移量,得到结果为2,表示 ptr1 与 ptr2 之间有2个元素。

需要注意的是,减法运算的结果的类型是 ptrdiff_t,它是 stddef.h 头文件中定义的整数类型。它根据平台的位数和编译器的实现可能有所不同。因此,在打印结果时,可以使用 %td 格式说明符来匹配 ptrdiff_t 类型的值。

此外,减法运算也可用于计算指针相对于基准指针的偏移量。通过将一个指针减去另一个指针,可以获得它们之间的偏移量,以字节数为单位。这对于在数组或缓冲区中位置计算非常有用。

注意:
1.只有当两个指针指向同一个数组中的元素时,指针相减才有意义,其意义为指针所指元素下标差。

2.当两个指针指向的元素不在同一个数组中时,结果未定义。

三、指针的关系运算

指针的关系运算符用于比较指针的大小关系,判断它们在内存中的相对位置。以下是指针的关系运算符及其示例用法:

大于运算符 (>):用于比较两个指针的大小,如果左侧指针指向的地址在内存中比右侧指针的地址大,则关系表达式的结果为真。

int main() {
    int arr[5] = {1, 2, 3, 4, 5};

    int* ptr1 = arr[0];
    int* ptr2 = arr[2];

    if (ptr2 > ptr1) {
        printf("ptr2 is greater than ptr1.\n");
    } else {
        printf("ptr2 is not greater than ptr1.\n");
    }

    return 0;
}

输出结果:

ptr2 is greater than ptr1.

在这个例子中,我们定义了一个整型数组arr,并使用指针ptr1和ptr2分别指向数组的不同元素。通过使用大于运算符(>)比较ptr2和ptr1,我们可以判断ptr2指向的地址是否在ptr1指向的地址之后。

小于运算符 (<):用于比较两个指针的大小,如果左侧指针指向的地址在内存中比右侧指针的地址小,则关系表达式的结果为真。针对上述示例进行修改:

int main() {
    int arr[5] = {1, 2, 3, 4, 5};

    int* ptr1 = arr[2];
    int* ptr2 = arr[4];

    if (ptr1 < ptr2) {
        printf("ptr1 is less than ptr2.\n");
    } else {
        printf("ptr1 is not less than ptr2.\n");
    }

    return 0;
}

输出结果:

ptr1 is less than ptr2.

在这个例子中,我们修改了指针ptr1和ptr2分别指向了数组arr的不同元素。通过使用小于运算符(<)比较ptr1和ptr2,我们可以判断ptr1指向的地址是否在ptr2指向的地址之前。

需要注意的是,指针的关系运算符只能用于两个指针之间的比较,不能用于指针和其他类型的变量之间的比较。此外,比较时需要确保两个指针指向相同的数组或在相同的内存块中,否则结果可能是未定义的。

四、指针比较运算

指针的比较运算可以用于判断两个指针是否指向同一个对象或确定它们在内存中的相对位置。以下是一个示例,展示了指针比较运算的用法:

#include <stdio.h>

int main() {
    int var1 = 5;
    int var2 = 10;

    int* ptr1 = &var1;
    int* ptr2 = &var2;
    int* ptr3 = &var1;

    // 比较ptr1和ptr2
    if (ptr1 == ptr2) {
        printf("ptr1 and ptr2 point to the same location.\n");
    } else {
        printf("ptr1 and ptr2 point to different locations.\n");
    }

    // 比较ptr1和ptr3
    if (ptr1 == ptr3) {
        printf("ptr1 and ptr3 point to the same location.\n");
    } else {
        printf("ptr1 and ptr3 point to different locations.\n");
    }

    return 0;
}

输出结果:

ptr1 and ptr2 point to different locations.
ptr1 and ptr3 point to the same location.

在这个例子中,我们定义了两个整数变量var1和var2,并使用指针ptr1、ptr2和ptr3分别指向它们。通过使用相等运算符==来比较指针,我们可以判断指针是否指向相同的内存位置。

在第一个比较中,ptr1和ptr2指向不同的变量var1和var2,因此输出是"ptr1 and ptr2 point to different locations."。

在第二个比较中,ptr1和ptr3都指向同一个变量var1,因此输出是"ptr1 and ptr3 point to the same location."。

需要注意的是,指针比较运算只比较指针的值,即它们所指向的内存地址。它们并不比较指针所指向的对象的值。如果需要比较指针所指向对象的值,应该使用间接引用运算符*来获取指针所指向的对象的值,并进行比较。

总结

本篇文章我们主要就是讲解了指针的运算,这些大家必须牢牢掌握。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。