当前位置: 首页 > article >正文

C语言变量指针、指针变量、数组指针、指针数组

变量指针与指针变量

指针变量指向数组

通过指针引用数组元素

引用一个数组元素,可以用:

①下标法:a[i]

②指针发:*(a+i)、 *(p+i)其中a数组名,p是指向数组元素的指针变量,其初值:p = a

案例:

需求有一整型数组a,有十个元素。输出数组中全部元素。

分析:要输出各元素的值,有三种方法

  • 下标法:通过改变下标输出所有元素
#include <stdio.h>

void main()
{
	int arr[10];
    //初始化数组
	for(int i = 0;i < 10;i++)
        scanf("%d",&arr[i]);
    //遍历元素
    for(int j = 0;j < 10;j++)
        printf("%-4d",a[j]);
    
    printf("\n");
}
  • 指针法(地址法):通过数组名计算数组元素地址,找出数组元素
#include <stdio.h>

void main()
{
	int arr[10];
    //初始化数组
	for(int i = 0;i < 10;i++)
        scanf("%d",&arr[i]);
    //遍历元素
    for(int j = 0;j < 10;j++)
        printf("%-4d",*(a+j));
    
    printf("\n");
}
  • 指针法(指针变量):用指针变量指向数组元素
#include <stdio.h>

void main()
{
	int arr[10];
    int *p=a;
    //初始化数组
	for(int i = 0;i < 10;i++)
        scanf("%d",&arr[i]);
    //遍历元素
    for(;p < (a + 10);p++)
        printf("%-4d",*p);
    
    printf("\n");
}

以上三种写法比较:

  • 第一种写法和第二种写法执行效率相同,系统是将a[i]转换成*(a+i)处理,即先计算处地址,因此比较费时。
  • 第三种比第一二中方法快,用指针变量直接指向数组元素,不必每次重新计算地址。(p++)可以大大提高执行效率
  • 第一张写法比较直观而已地址法或指针变量方法难以很快判断出当前处理元素。

使用指针变量指向数组元素时(第三种写法),注意以下三点:

  1. *(p--)相当于a[i--],先*p,再 p--
  2. *(++p)相当于a[++i],先++p,再*
  3. *(--p)相当于a[--i],先--p,再*

数组名作函数参数

表现形式:

  1. 形参和实参都是数组名

    void fun (int arr[],int len){...}
    
    void main()
    {
        int arr[] = {1,2,3};
        fun(arr,sizeof(arr)/sizeof(arr[0]))
    }
    
  2. 实参用数组名,形参用指针变量

    void fun (int *p,int len){...}
    
    void main()
    {
        int arr[] = {1,2,3};
        fun(arr,sizeof(arr)/sizeof(arr[0]))
    }
    
  3. 实参形参都用指针变量

    void fun (int *p,int len){...}
    
    void main()
    {
        int arr[] = {1,2,3};
        int *p = arr;
        fun(p,sizeof(arr)/sizeof(arr[0]))
    }
    
  4. 实参为指针变量,形参为数组名

    void fun (int arr[],int len){...}
    
    void main()
    {
        int arr[] = {1,2,3};
        int *p = arr;
        fun(p,sizeof(arr)/sizeof(arr[0]))
    }
    
案例

需求:将数组a中n个整数按相反顺序存放

#include <stdio.h>

/*
数组的反转
*/

void inv(int arr[], int len)
{
    int temp;
    // 反转思路:将第0个和n-1个进行对调
    for (int i = 0; i < len / 2; i++)
    {
        temp = arr[i];
        arr[i] = arr[len - i - 1];
        arr[len - i - 1] = temp;
    }
}

void getarr(const int arr[], int len)
{
    for (int i = 0; i < len; i++)
    {
        printf("%-3d", arr[i]);
    }
    printf("\n");
}

/*
数组的反转:指针实现
const:是变量变成只读变量不能修改
*/
void inv2(int *p, const int len)
{
    int *i = p, *j = &p[len - 1], temp;
    for (; i < j; i++, j--)
    {
        temp = *i;
        *i = *j;
        *j = temp;
    }
}

int main()
{
    int arr[] = {1, 2, 3, 4, 5};
    getarr(arr, sizeof(arr) / sizeof(arr[0]));
    inv2(arr, sizeof(arr) / sizeof(arr[0]));
    getarr(arr, sizeof(arr) / sizeof(arr[0]));

    return 0;
}

数组指针与指针数组

数组指针

概念:数组指针是指向数组的指针,本质上还是指针

特点:

  • 先有数组,后有指针
  • 它指向的是一个完整的数组

一维数组指针:

数据类型 (*指针变量名)[容量];

案例:

#include <stdio.h>

/*
数组指针:指向数组的指针(并不是指向数组元素的指针)
*/
int main()
{
    // 一维数组指针
    // 现有数组,再有指针
    int arr[] = {11, 22, 33, 44, 55, 66, 77, 88, 99};
    int len = sizeof(arr) / sizeof(arr[0]);
    // int *p = arr; // 指向数组的第一个元素 p++(指针变量)

    int(*p)[9] = &arr; // 此时p不是指向arr数组第一个元素,而是指向arr数组本身
    printf("%p\n", p);

    //p++;此时p++会跳出整个数组,访问到一块未知的内存程序中尽量避免
    //如何访问数组指针
    printf("%d\n",(*p)[0]);//(*p)注意括号

    //遍历
    for (int i = 0; i < len; i++)
    {
        printf("%-3d",(*p)[i]);
    }
    
    

    return 0;
}

指向数组元素的指针,本质上还是指针变量;现在指向数组的指针,叫做数组指针。

二维数组指针:

数据类型 (*指针变量名)[行容量][列容量]

案例:

写法一:

#include <stdio.h>

int main()
{
    int arr[][2] = {10, 20, 100, 200};

    // 创建二维数组指针
    int(*p)[2][2] = &arr;

    printf("%d\n", (*p)[1][0]);


    //遍历
    for (int i = 0; i < sizeof(arr)/sizeof(arr[0]); i++)
    {
        int len =sizeof(arr[i])/sizeof(int);
        for (int j = 0; j < len; j++)
        {
            printf("%-5d",(*p)[i][j]);
        }
        printf("\n"); 
    }
    

    return 0;
}

写法二:

#include <stdio.h>

int main()
{
    int arr[][2] = {10, 20, 100, 200};

    // 创建二维数组指针
    int(*p)[2][2] = &arr;
    int(*q)[2] = arr;

    // 遍历
    for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
    {
        int len = sizeof(arr[i]) / sizeof(int);
        for (int j = 0; j < len; j++)
        {
            printf("%-4d,%-4d,%-4d", *(*(q + i) + j), *(q[i] + j), q[i][j]);
        }
        printf("\n");
    }

    return 0;
}
  • 指针和数组中符号优先级:() > [ ] > *
  • 通过指针引用多维数组

案例

需求:用指向元素的指针变量输出二维数组元素的值

#include <stdio.h>

int main()
{
    int a[3][3] = {1, 2, 3, 4, 5, 6, 7, 8, 9};

    int *p = a[0]; // 或者&arr[0][0]

    printf("%d", *a[0]);    //a[0]中的a是行[]是列

    // 循环遍历
    for (; p < a[0] + 9; p++)
    {
        if ((p - a[0]) % 3 == 0)
        {
            printf("\n");
        }
        printf("%-4d",*p);
    }
    printf("\n");
    return 0;
}

案例

需求:数组指针输出二维数组任意行任意列元素的值

#include <stdio.h>

int main()
{
    int a[3][4] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};

    int(*p)[4] = a; // 或者&arr[0]数组指针[]写列的大小

    //创建两个行列对应行于列
    int row,col;
    printf("请输入行号列号:\n");
    scanf("%d%d",&row,&col);

    printf("arr[%d][%d]=%d\n",row,col,*(*(p+row)+col));

    return 0;
}

指针数组

概念:指针数组是一个数组,数组中的每一个元素都是指针

特点:现有指针,后有数组。本质上还是数组,其中的元素类型为指针

数据类型 *数组名[容量];

案例:

#include <stdio.h>

int main()
{
    int a = 10, b = 20, c = 30;

    // 定义指针数组,指针数组存放指针
    int *arr[3] = {&a, &b, &c};

    // 获取数组大小
    int len = sizeof arr / sizeof arr[0];

    // 遍历
    for (int i = 0; i < len; i++)
    {
        printf("%-3d", *arr[i]);    //输出每个值都需要解引用
    }
    printf("\n");

    return 0;
}

建议:指针数组处理字符串


http://www.kler.cn/a/454238.html

相关文章:

  • 【ES6复习笔记】rest参数(7)
  • 基于aspose.words组件的word bytes转pdf bytes,去除水印和解决linux中文乱码问题
  • 详细对比JS中XMLHttpRequest和fetch的使用
  • WebRTC服务质量(11)- Pacer机制(03) IntervalBudget
  • 数据仓库和数据湖 数据仓库和数据库
  • C 实现植物大战僵尸(一)
  • 流程图(二)利用python绘制网络图
  • shardingsphere分库分表项目实践5-自己用java写一个sql解析器+完整项目源码
  • 探秘“香水的 ChatGPT”:AI 开启嗅觉奇幻之旅!
  • 【自留】Unity VR入门
  • [原创](Modern C++)现代C++的第三方库的导入方式: 例如Visual Studio 2022导入GSL 4.1.0
  • python之打印、变量、格式化输出
  • SkyWalking服务监控、追踪、诊断可视化工具
  • Flink的Watermark水位线详解
  • 嵌入式学习-QT-Day09
  • Linux 简单命令总结
  • Android笔记(四十):ViewPager2嵌套RecyclerView滑动冲突进一步解决
  • 企业如何搭建安全的跨网文件安全交换管理系统
  • 人工智能的视觉天赋:一文读懂卷积神经网络
  • Unity 应用程序中集成 Web 浏览器功能
  • linux、mysql日常工作备忘录
  • Redis 应用场景深度探索
  • docker hub 官方redis镜像使用方法
  • 抓取手机HCI日志
  • MR眼镜如何接管我们的手机生活
  • pikachu靶场RCE漏洞