c语言指针详解(上)

目录

一、指针的基本概念和用法

二、指针运算

[2.1 指针的自增和自减运算](#2.1 指针的自增和自减运算)

[2.2 指针的自增和自减运算](#2.2 指针的自增和自减运算)

三、数组和指针

四、指针和函数

[4.1 在函数中使用指针作为参数和返回值](#4.1 在函数中使用指针作为参数和返回值)

[4.1.1 使用指针作为函数参数](#4.1.1 使用指针作为函数参数)

[4.1.2 使用指针作为函数返回值](#4.1.2 使用指针作为函数返回值)

[4.2 指针参数的传值和传引用特性](#4.2 指针参数的传值和传引用特性)

[4.2.1 指针参数的传值特性](#4.2.1 指针参数的传值特性)

[4.2.2 指针参数的传引用特性](#4.2.2 指针参数的传引用特性)


🌈嗨!我是Filotimo__🌈。很高兴与大家相识,希望我的博客能对你有所帮助。

🎁欢迎大家给我点赞👍、收藏⭐️,并在留言区📝与我互动,这些都是我前进的动力!

🌟我的格言:森林草木都有自己认为对的角度🌟。

一、指针的基本概念和用法

在 C 语言中,指针是一个变量,用来存储一个地址,这个地址指向内存中的另外一个变量。可以通过指针来访问或修改这个变量的值。
使用 * 运算符可以访问指针所指向的变量的值。

使用 & 运算符可以获取变量的地址。

下面是一个使用指针访问变量地址和值的示例代码:

cpp 复制代码
#include <stdio.h>

int main() {
    int num = 42;       // 定义一个整数变量 num 并初始化为 42
    int *ptr = &num;    // 定义一个指针变量 ptr 并将其初始化为 num 的地址

    printf("num 的地址是:%p\n", &num);
    printf("ptr 所指向的地址是:%p\n", ptr);
    printf("ptr 所指向的值是:%d\n", *ptr);

    return 0;
}

输出结果如下:

在上面的示例代码中,我们首先定义了一个整型变量 num 并初始化赋值为 42,然后定义一个整型指针变量 ptr ,并使用 & 运算符取 num 变量的地址初始化 ptr 指向 num 变量的地址。接着我们通过 printf 函数输出 num 变量的地址和 ptr 指向的地址,最后输出通过 *ptr 来访问 ptr 指向的变量 num 的值。

二、指针运算

2.1 指针的自增和自减运算

自增和自减运算仅适用于指向数组、字符串或分配内存的指针。

自增运算符 ++ 让指针指向下一个内存单元,即指针变量的值加上所指向的变量类型占用的字节数。

自减运算符 -- 让指针指向前一个内存单元,即指针变量的值减去所指向的变量类型占用的字节数。

示例代码:

cpp 复制代码
#include <stdio.h>

int main() {
    int arr[5] = {1, 2, 3, 4, 5};
    int *p = &arr[0];   // 指向数组 arr 的第一个元素的指针

    printf("当前指针 p 的值为: %p\n", p);
    p++;                // 指针自增操作
    printf("执行 p++ 后,p 指向的值为: %d\n", *p);

    p--;                // 指针自减操作
    printf("执行 p-- 后,p 指向的值为: %d\n", *p);

    return 0;
}

输出结果如下:

这段代码中,我们定义了一个包含 5 个整型元素的数组 arr,并定义一个指向数组第一个元素的指针 p。通过执行 p++p-- 操作,指针 p 的值发生了变化,指向了数组中不同的元素,从而可以访问数组中不同的数据。

2.2 指针的自增和自减运算

加法和减法运算可以应用于指向数组或分配内存的指针。如果对指针进行加法或减法运算,会根据指针所指向类型的字节大小来确定位移量。

指针的加法运算(+)将指针的值增加多个字节数。

指针的减法运算(-)将指针的值减去多个字节数。

示例代码:

cpp 复制代码
#include <stdio.h>

int main() {
    int arr[] = {1, 2, 3, 4, 5};
    int *p = &arr[2];   // 指向数组 arr 的第三个元素的指针

    printf("当前指针 p 的值为: %p\n", p);
    
    p = p + 1;          // 指针加法操作
    printf("执行 p + 1 后,p 指向的值为: %d\n", *p);
    
    p = p - 2;          // 指针减法操作
    printf("执行 p - 2 后,p 指向的值为: %d\n", *p);

    return 0;
}

输出结果如下:

在这个示例中,我们定义了一个数组 arr,并将指针 p 初始化为指向数组 arr 的第三个元素。通过执行 p + 1p - 2 操作,指针 p 的值发生了相应的变化,通过访问指针 p 所指向的值,我们可以看到指针指向了数组中不同的元素。

三、数组和指针

数组名本身就是指向数组头部的指针。

例如,如果有一个 int 类型的数组 arr,那么在代码中使用 arr&arr[0] 是等效的,在内存中它们所指向的都是数组的第一个元素。

示例代码:

cpp 复制代码
#include <stdio.h>

int main() {
    int arr[] = {1, 2, 3, 4, 5};
    int *p = arr;       // 指向数组 arr 的第一个元素的指针

    printf("通过数组名访问数组的第一个元素:%d\n", arr[0]);
    printf("通过指针访问数组的第二个元素:%d\n", *(p + 1));
    printf("通过指针访问数组的第三个元素:%d\n", p[2]);

    return 0;
}

输出结果如下:

四、指针和函数

4.1 在函数中使用指针作为参数和返回值

4.1.1 使用指针作为函数参数

可以通过将指针作为函数的参数来传递数据。这样可以实现在函数内部修改传递给函数的变量的值,因为指针传递的是变量的地址。

示例代码:

cpp 复制代码
#include <stdio.h>

void changeValue(int *ptr) {
    *ptr = 10;   // 修改指针指向的变量的值
}

int main() {
    int num = 5;
    printf("函数调用前的值:%d\n", num);
    changeValue(&num);   // 传递变量的地址
    printf("函数调用后的值:%d\n", num);
    
    return 0;
}

输出结果如下:

在这个示例中,我们在 changeValue 函数中使用了一个指针参数 ptr,通过 *ptr 修改了变量 num 的值。在 main 函数中将 num 的地址传递给 changeValue 函数来实现修改 num 的值。

4.1.2 使用指针作为函数返回值

可以使用指针作为函数的返回值,以便将函数内部的计算结果返回给调用函数。

示例代码:

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>   // 包含 malloc 和 free 函数

int* createArray(int size) {
    int *arr = (int*)malloc(size * sizeof(int));   // 动态分配内存,并强制类型转换
    for (int i = 0; i < size; i++) {
        arr[i] = i + 1;
    }
    return arr;
}

int main() {
    int size = 5;
    int *array = createArray(size);   // 函数返回指针
    for (int i = 0; i < size; i++) {
        printf("%d ", array[i]);
    }
    free(array);   // 释放内存
    
    return 0;
}

输出结果如下:

在这个示例中,createArray 函数根据传入的参数 size 动态分配了一个整型数组,并将数组的首地址作为指针返回给调用函数。在 main 函数中,我们通过调用 createArray 函数来获取数组的地址,并使用指针 array 访问和输出数组的元素。最后,释放动态分配的内存。

4.2 指针参数的传值和传引用特性

4.2.1 指针参数的传值特性

当将指针作为函数参数进行传递时,实际上传递的是指针变量的值(即地址)。这意味着函数内部对指针本身的修改不会影响到调用该函数的代码。

示例代码:

cpp 复制代码
#include <stdio.h>

void changePointer(int *ptr) {
    int dummy = 10;
    ptr = &dummy;   // 修改指针的值
}

int main() {
    int num = 5;
    int *ptr = &num;
    printf("函数调用前的指针:%p\n", ptr);
    changePointer(ptr);
    printf("函数调用后的指针:%p\n", ptr);

    return 0;
}

输出结果如下:

在这个示例中,changePointer 函数尝试将指针 ptr 指向一个新的变量 dummy,但是在函数外部输出指针 ptr 的值时并未改变,验证了指针参数的传值特性。

4.2.2 指针参数的传引用特性

通过使用指针的指针或者指针的引用,可以实现对指针的引用传递,从而在函数内部对指针进行修改可以影响到调用该函数的代码。

示例代码:

cpp 复制代码
#include <stdio.h>

void changePointer(int **ptr) {
    int dummy = 10;
    *ptr = &dummy;   // 修改指针指向的地址
}

int main() {
    int num = 5;
    int *ptr = &num;
    printf("函数调用前的指针:%p\n", ptr);
    changePointer(&ptr);
    printf("函数调用后的指针:%p\n", ptr);

    return 0;
}

输出结果如下:

在这个示例中,我们将指针 ptr 的地址传递给 changePointer 函数,并在函数内部修改了指针 ptr 的值为新的变量 dummy 的地址。在函数外部输出指针 ptr 的值时发现已经改变,验证了指针参数的传引用特性。

相关推荐
LaoWaiHang3 分钟前
C语言从头学61——学习头文件signal.h
c语言
环能jvav大师8 分钟前
基于R语言的统计分析基础:使用SQL语句操作数据集
开发语言·数据库·sql·数据分析·r语言·sqlite
吱吱鼠叔12 分钟前
MATLAB方程求解:1.线性方程组
开发语言·matlab·php
菜鸟求带飞_12 分钟前
算法打卡:第十一章 图论part01
java·数据结构·算法
浅念同学13 分钟前
算法.图论-建图/拓扑排序及其拓展
算法·图论
Antonio91517 分钟前
【CMake】使用CMake在Visual Studio内构建多文件夹工程
开发语言·c++·visual studio
是小Y啦30 分钟前
leetcode 106.从中序与后续遍历序列构造二叉树
数据结构·算法·leetcode
LyaJpunov30 分钟前
C++中move和forword的区别
开发语言·c++
@月落34 分钟前
alibaba获得店铺的所有商品 API接口
java·大数据·数据库·人工智能·学习
程序猿练习生35 分钟前
C++速通LeetCode中等第9题-合并区间
开发语言·c++·leetcode