C语言 / 指针相关内容总结

该博客主要对C语言中指针相关内容进行总结,聚焦于信息技术领域中C语言编程里指针这一重要知识点。

指针相关内容总结

 

项目

格式      

描述

代码案例

通用类型指针      

void *指针变量名 

可以指向任意类型的地址,但是使用是需要类型强转,多用于传参和返回

int main(int argc, const char *argv[])

{

    int a = 16;

    void *ptr = &a;

    printf("*ptr = %d\n", *(int *)ptr);

    return 0;

}

 

函数指针数组

存储类型 数据类型 (*函数指针数组变量名[常量表达式])(参数列表)

常量表达式:数组元素的个数

函数指针数组:

本质上是一个数组,数组的元素是函数指针

float Add(float a, float b){

    return a + b;

}

float Sub(float a, float b){

    return a-b;

}

float Mul(float a, float b){

    return a*b;

}

float Div(float a, float b)

{

    return a/b;

}

int main(int argc, const char *argv[])

{

   

    float (*p1)(float, float)=Add;

    float (*p2)(float, float)=Sub;

    float (*p3)(float, float)=Mul;

    float (*p4)(float, float)=Div;

    float a=50,b=2;

    float (*p[4])(float, float)={Add, Sub, Mul, Div};

    for(int i=0;i<4;i++)

    {

    //    p[0]-->Add

    //        Add(a, b);

        float s=p[i](a, b);

        printf("s=%.2f\n", s);

    }

    return 0;

}

函数指针

存储类型 数据类型 (*函数指针变量名)(参数列表)

本质上是一个指针,用来指向函数的首地址,多用于回调函数

void Add(void) à void (*p)(void) = Add

void Add(int a, float b) à void (*p)(int, float) = Add

int Add() à int (*p)() = Add

int Add(int a, float b) à int (*p)(int a, float b) = Add

指针函数

数据类型 *函数名(参数列表)

    {

        函数体;

        return 地址;   

    }

本质上是一个函数,返回一个地址.

注意: 不可以返回局部变量的地址

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

int *fun() //指针函数

{

    int a = 20, b = 10;

    int arr[2];

    arr[0] = a;

    arr[1] = b;

    return arr;

}

// 注意: 上面这个函数并不能返回arr, 因为arr是局部变量, 函数结束时, arr就被系统回收了

//解决方法1:

//把数组放到全局,延长生命周期的效果

int arr[2];

int *fun1()//指针函数

{

    int a=20,b=10;

    arr[0] = a;

    arr[1] = b;

    return arr;

}

//解放方式2:

//把数据作为参数传递

int *fun2(int *arr)//指针函数

{

    int a=1,b=100;

    *arr=a;

    *(arr+1)=b;

    return arr;

}

//解决方式3:

//把内存放到堆区malloc, 堆区的内存系统不会主动回收, 需要程序员手动回收, 这样就可以自己控制这部分内存的生命周期

//void *malloc(size_t size)

//size_t size: 表示在堆区申请的内存大小

//void *: 申请成功返回堆区的首地址,失败返回NULL

int *fun3()

{

    int a = 20, b = 100;

    int *p = (int *)malloc(8);

    *p = a;

    *(p+1) = b;

    return p;

}

字符指针数组

char *指针数组名[常量表达式]

本质上是一个数组,每个都是字符类型指针

#include <string.h>

#include <stdlib.h>

#include <stdio.h>

int main(int argc, const char *argv[])

{

    char a[] = "abcd";

    char b[] = "ABCD";

    char c[] = "1234";

       

    //char *p1 = a;

    //char *p2 = b;

    //char *p3 = c;

       

    //字符指针数组指向变量的地址

    char *p[3] = {a, b ,c};

       

    *(*(p+1)+3) ='3'; //修改第1行,第3列的值

    for(int i=0; i < 3; i++){

        //puts(p[i]);

        //puts(*(p+i));

        printf("p[%d] = %s\n", i, p[i]);

        printf("*(p+%d) = %s\n", i,*( p+i));

    }  

    putchar(10);

    char *q[3] = {"abcd", "ABCD", "1234"};

        // *(*(q+1)+3) ='3'; // not ok

//常量不能被修改

        for(int i=0; i<3; i++){

            printf("q[%d] = %s\n",i, q[i]);

        }  

    return 0;

指针数组

存储类型 数据类型 *指针数组变量名[常量表达式]

常量表达式表示元素的个数

本质上是一个数组, 数组的元素是类型相同的指针

int a=1, b=2, c=3, d=4; // à int arr[4]

int *p1=&a;

int *p2=&b;

int *p3=&c;

int *p4=&d;

int *p[4]={&a, &b, &c, &d};

// p[0] à&a

// p[1] à&b

// p[0] à&a

// p[0] à&a

数组指针

存储类型 数据类型 (*指针变量名)[常量表达式]

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

int (*p)[3] = arr;

本质上是一个指针,用来指向二维数组的地址,多用于传参和返回

  1. ()不可以省略,为了突出指针,注: 运算优先级() > [] > *
  2. 常量表达式: 需要和二维数组的列数保持一致

#include <string.h>

#include <stdlib.h>

#include <stdio.h>

int main(int argc, const char *argv[])

{

    int arr[2][3]  = {11, 22, 33, 44, 55, 66};

    int (*p)[3] = arr;

    //找第2行第3列元素 arr[1][2]

    //arr --> 第1行的行地址

    //arr+1 -->第2行的行地址

   

    //*代表降维

    //*(arr+1) à第2行第1列地址

    //*(arr+1)+2 à第2行第3列的地址

    //*(*(arr+1)+2) --> 第二行第三列的值

    //m行n列的元素 -->*(*(arr+m-1)+n-1)

    //

    //arr -->

    //*arr --> arr[0]

    //*(arr+1) --> arr[1]

    //*(arr+1) --> arr[i]

    //地址

    for(int i=0; i<2; i++){

        for(int j=0; j<3; j++){

            printf("&arr[%d][%d]       = %p\n",i,j, &arr[i][j]);

            //arr[i][j]是值,&取地址

            printf("*(arr + %d) + %d   = %p\n",i,j, *(arr+ i) + j);

            //arr 是首行地址,

            //arr + i 是 首行+i行地址,

            //*(arr + i) 是arr+i的首列地址,

            //*(arr + i) + j à首行+i行,首列+j列元素的地址

            printf("arr[%d]) + %d      = %p\n",i,j, arr[i] + j);

            //arr[i]表示第i行的首地址, 

            //arr[i] + j; 第i行偏移j列元素的地址

            putchar(10);

            printf("&p[%d][%d]         = %p\n",i,j, &p[i][j]);

            printf("*(p+%d) + %d       = %p\n",i,j, *(p+i)) + j;

            printf("p[%d] + %d)        = %p\n",i,j, p[i] + j);

       

            putchar(10);

        }

        putchar(10);

    }

    //值

    for(int i=0; i<2; i++){

        for(int j=0; j<3; j++){

            printf("arr[%d][%d]           = %d\n",i,j, arr[i][j])e

            //arr[i][j]是值

            printf("*(*(arr + %d) + %d)   = %d\n",i,j, *(*(arr+ i) + j));

            //arr 是首行地址,

            //arr + i 是 首行+i行地址,

            //*(arr + i) 是arr+i的首列地址,

            //*(arr + i) + j --->首行+i行, 首列+j列元素的地址

            //在地址上加*就是值

            printf("*(arr[%d]) + %d)      = %d\n",i,j,*(arr[i] + j));

            //arr[i]表示第i行的首地址, 

            //arr[i] + j; 第i行偏移j列元素的地址

            //在地址上加*就是值

            putchar(10);

            printf("&p[%d][%d]            = %d\n",i,j, p[i][j]);

            printf("*(*(p+%d) + %d)       = %d\n",i,j, *(*(p+i) + j));

            printf("*(p[%d] + %d))        = %d\n",i,j, *(p[i] + j));

       

            putchar(10);

        }

        putchar(10);

    }

    return 0;

}                                                                                                                                                                                                                                   

~                

二维数组和指针

列:&arr[0][0] -->arr[0] -->&p[0][0] -->p[0]

行:&arr[0]-->arr--->&p[0]--->p

整个二维数组:&arr

偏移指针大小:&p--->&p+1

#include <string.h>

#include <stdlib.h>

#include <stdio.h>

int main(int argc, const char *argv[])

{

    int arr[2][3] = {11, 22, 33, 44, 55, 66};

    int (*p)[3] = arr;

    printf("column:\n");

    printf("&arr[0][0]     = %p\n", &arr[0][0]);

    printf("&arr[0][0] + 1 = %p\n", &arr[0][0] + 1);

    printf("&p[0][0]     = %p\n", &p[0][0]);

    printf("&p[0][0] + 1 = %p\n", &p[0][0] + 1);

   

    printf("arr[0]         = %p\n", arr[0]);

    printf("arr[0] +1      = %p\n", arr[0]+1);

    printf("p[0]         = %p\n", p[0]);

    printf("p[0] +1      = %p\n", p[0]+1);

    printf("row:\n");

    printf("&arr[0]        = %p\n", &arr[0]);

    printf("&arr[0] + 1    = %p\n", &arr[0]+1);

    printf("&p[0]        = %p\n", &p[0]);

    printf("&p[0] + 1    = %p\n", &p[0]+1);

    printf("arr            = %p\n", arr);                                                            

    printf("arr + 1        = %p\n", arr + 1);

    printf("whole 2d array:\n");

    printf("&arr           = %p\n", &arr);

    printf("&arr + 1       = %p\n", &arr + 1);

    return 0;

}

多级指针

存储类型  数据类型**指针变量名   (*的个数任意)

一级指针存储普通变量的地址

二级指针存储一级指针的地址

三级指针存储二级指针的地址

#include <string.h>

#include <stdlib.h>

#include <stdio.h>

int main(int argc, const char *argv[])

{

    int a = 10;

    int *p = &a;

    int **q = &p;

    int ***m = &q;

    //值

    printf("a=%d, *p=%d, **q=%d, ***m=%d\n", a, *p, **q, ***m);

    //a 地址

    printf("&a=%p, p=%p, *q=%p, **m=%p\n", &a, p, *q, **m);

    //p 的地址

    printf("&p=%p, q=%p, *m=%p\n", &p, q,  **m);

    //q的地址

    printf("&q=%p, m=%p\n", &q, *m);

    //m的地址

    printf("&m=%p\n", &m);

   

    return 0;

}   

指针和字符数组

char str[]="hello";

char *p=str;

#include <string.h>

#include <stdlib.h>

#include <stdio.h>

//

//字符指针指a向字符数组的地址

//

int main(int argc, const char *argv[])

{

    char str[20]="hello";

    char *p=str; //p-->str

    gets(str);

    puts(str);

    // 1.指针可以替换字符数组的使用

    gets(p);

    puts(p);

    // 2.指针指向字符数组可以修改

    *(p+1)='E';

    puts(p);

    // 3.不同的字符数组存储相同字符串,数组地址不同

    char a[]="1234";

    char b[]="1234";

    printf("a=%p b=%p\n",a,b);

    char *pstr = "hello";//p指向字符串常量hello的首地址

    // a.指针指向字符串常量不可以修改,段错误

        //    *(p+1)='E';

        //    puts(p);                                                                     

    // 2.不同的指针指向同一个字符串常量,则地址一样

    char *qstr = "hello";

    printf("p=%p\n q=%p\n",p,q);

    // b.字符指针指向字符串常量的地址

    return 0;

}

一维数组和指针

数据类型  *指针变量名=数组名

int arr[] = {11,22,33};

int *p=arr;

一维数组名表示数组的首地址,既第一个元素的地址, 数组名是常量不可自增或自减

&arr[0]--->arr--->&p[0]--->p 偏移一个元素字节大小

&arr 偏移整个一维数组

&p 偏移一个指针字节大小

地址等价关系:

&arr[i]à &p[i]à

arr+Ià p+ià p++

值等价关系:

arr[i]à p[i]à

*(arr+i)à *(p+i)à *p++

#include <string.h>

#include <stdlib.h>

#include <stdio.h>

int main(int argc, const char *argv[])

{

    int arr[] = {11, 22, 33, 44};

    int *p = arr; //

    printf("&arr[0] = %p\n", &arr[0]);

    printf("&arr[0] + 1 = %p\n", &arr[0] + 1);

    printf("arr = %p\n", arr);

    printf("arr + 1 = %p\n", arr + 1);

    printf("&arr = %p\n", &arr);

    printf("&arr + 1 = %p\n", &arr + 1);

   

    printf("&p[0] = %p\n", &p[0]);

    printf("&p[0] + 1 = %p\n", &p[0] + 1);

    printf("p = %p\n", p);

    printf("p + 1 = %p\n", p + 1);

    printf("&p = %p\n", &p);

    printf("&p + 1 = %p\n", &p + 1);

    return 0;

指针的运算

算数运算

+ - ++ --

int a=10;

int *p=&a;

a: 值

&a:a地址,4字节的首编号

p:a地址,4字节的首编号

*p: a的值

&p: p的地址,8字节的首编号

+

int a=10;int *p=&a

  • p+n向高地址偏移数据类型*n字节
  • &a+n向高地址偏移数据类型*n字节
  • *p+n先取值, 对值加n
  • &p+n向高地址当先偏移8*n字节
  • *(p+n)先向高地址方向偏移数据类型*n字节,再取值

-

int a=10;int *p=&a

  • pn向低地址偏移数据类型*n字节
  • &an向低地址偏移数据类型*n字节
  • *pn先取值,对值减n
  • &pn向低地址偏移8*n字节
  • *(pn)先向低地址方向偏移数据类型*n字节,再在取值
  • pq(连续内存)p到q之间元素的个数

++

只能对变量++运算

int a=10; &a是常量,不可以自增

int arr[]={11,22,33};

int *p=arr;

  • *++p先对p向高地址方向偏移1个数据类型字节,再在取值
  • ++*p先取值,对值加++
  • *p++先执行p++,但是++是后缀运算,先取值,后自增,先执行*p取值,p向高地址方向偏移1个数据类型字节
  • *(p++)先执行p++,但是++是后缀运算,先取值,后自增,先执行*p取值,p向高地址方向偏移1个数据类型字节
  • (*p)++先取值,对值加1
  • *(++p)先对p向高地址方向偏移1个数据类型字节大小,再取值

--

和++类似

算数运算

赋值运算

=

+=

-=

=

int a=10; int *p=&a

  • 指针p指向a的地址
  • 等号左右两端需要统一

+=

  • p+=1: p向高地址偏移一个数据类型字节
  • =: p-=1p向低地址偏移一个数据类节

算数运算

关系运算

int a=10;

int b=20;

一般适用于数组,数组的地址是连续

  • >: p>q成立返回1,不成立返回0
  • >=: p>=q成立返回1,不成立返回0
  • <: p<q成立返回1,不成立返回0
  • <=: p<=q成立返回1,不成立返回0
  • ==: p==q成立返回1,不成立返回0
  • !=: p!=q成立返回1,不成立返回0

解引用和取地址

*: 解引用

&: 取地址

*:乘法,标识符,取值

&:逻辑与,按位与,取地址

int a=100;

int *p=&a;

*p=a=100

p=&a

带*表示值,不带*表示地址

*和&属于逆运算

值:a--> *p--> *&a--> *(&a)

地址:&a--> p--> &*p--> &(*p)

指针变量的定义以及初始化

1.指针的类型和地址对应的数据类型建议保持一致(常用)

    int a=100;

    int *p=&a;

    double b=2.5;

    double *q=&b;

2.指针的类型和地址的类型不一致(不常使用),实际是小端存储

    int a=4626;

    char *p=&a;

    *p=18

3.可以使用已经初始化的指针变量为另一个指针变量初始化

    int a=100;

    int *p=&a;

    int *q=p;

4.指针未初始化,不可以直接使用,否则称为野指针

    野指针:访问非法的内存空间

    int *p;//未初始化的指针,计算机会随机指向内存

5.当指针不清楚指向谁的地址时,指向NULL

    int *p=NULL;

NULL:表示的0号地址,该地址不可以使用

6.指针的错误初始化

    int a = 100;

    int *p = a; × not ok

int *p = 100; ×not ok

7.不要使用静态类型的指针指向动态类型的变量地址

静态类型的内存先分配,动态类型的内存后分配

    int a;

    static int *p=&a; × not ok

指针的字节大小

指针的大小和操作系统有关,和数据类型无关

64位操作系统,指针8字节

32位操作系统,指针4字节

指针变量的定义

存储类型  数据类型 *指针变量名;

  1. 存储类型:static\auto\register\extern\const\volatile

  1. 数据类型:
    基类型、构造类型、空类型void,指针类型

3.*: 指针标志

4.指针变量名:
满足命名规范

int *p   
p的类型是int*,
int表示指针指向地址对应的值的类型,表示指针加减运算的偏移量

    float *p

    char *p

    void *p

   

    int a=100;

    int *p=&a;

打开链接下载源码: https://pan.quark.cn/s/05da658a2377 在信息技术领域中,输入法作为操作系统的一个核心构成部分,赋予了用户利用键盘输入多语种文字的能力。"ime-日语输入法安装必须文件"这一资源是一套为日语输入法部署而设计、包含全部必要元素的集成包,对于那些需要在个人计算机上执行日语文字输入的操作者而言具有不可替代的作用。接下来将深入剖析其中所包含的核心概念。 IME(Input Method Editor,输入法编辑器)是操作系统内的一种软件支持服务,其功能在于为非拉丁字符环境提供文字输入方案,例如中文、日文、韩文等文字系统。在日本地区,IME通常被用来将罗马字(罗马拼音)形式的输入转换为平假名、片假名乃至汉字。此压缩文件内含的日语IME文件夹即为执行这一转换功能的关键要素。 kbdjpn.dll被视为一个关键的系统性文件,其意指“Japanese Keyboard Layout”(日语键盘布局)。该动态链接库文件负责设定日语键盘的排列方式及快捷操作组合,使用户能够借助常规的QWERTY键盘输入日语文字。倘若缺少这一文件,即便已经安装了日语输入法,依然无法正常显示及输入日语字符。 另外,imjp81k.dll同样是一个重要的系统性构成,它属于日语IME的范畴,全称为“Input Method Japanese for Windows 8.1 and later, Katakana mode”(适用于Windows 8.1及更新版本的日语输入法,片假名模式)。该文件支持日语的片假名输入,是处理日语输入的核心组成部分。在安装或升级日语输入法的过程中,保证imjp81k.dll的准确性与完整性显得尤为关键。 压缩包所含的"Window...
内容概要:本文研究了基于DPWMA调制与正负序分离的ANPC三电平并网逆变器前馈控制策略,旨在解决传统三电平逆变器在谐波抑制、电网不平衡适应性及动态响应方面的技术瓶颈。通过构建融合双极性倍频脉宽调制(DPWMA)、正负序分离锁相控制与电网电压前馈的一体化控制体系,全面优化逆变器的输出波形质量、相位同步精度与抗扰能力。文章深入分析了ANPC三电平拓扑的结构优势,如开关损耗均衡、中点电位可控性强和电压利用率高等特点,并设计了包含信号采集、核心控制与调制驱动三层架构的完整控制系统。通过Simulink仿真平台对稳态运行、电网不平衡及动态扰动等多种工况进行验证,结果表明该策略显著降低了总谐波畸变率,提升了锁相精度与系统动态稳定性,有效增强了逆变器在复杂电网环境下的适应能力和运行可靠性。; 适合人群:具备电力电子、自动控制及新能源并网相关基础知识,从事新能源发电、微电网、电力系统仿真等领域的科研人员与工程技术人员,特别适合研究生及以上层次的研究者。; 使用场景及目标:①用于提升大功率并网逆变器在电网电压不平衡、谐波干扰和动态扰动等复杂工况下的运行性能;②为高电能质量要求的应用场景提供先进控制解决方案;③支持科研仿真、论文复现与实际工程项目中的高性能并网控制系统设计与优化。; 阅读建议:建议结合提供的Simulink仿真模型进行实践操作,重点理解DPWMA调制机制、正负序分离锁相算法与电网电压前馈控制之间的协同作用,按照文档结构系统学习,并与传统控制策略进行对比分析,以深入掌握改进策略的技术优势与实现细节。
代码下载链接: https://pan.quark.cn/s/d9794888cbc0 ### G代码经典解释程序知识点详解 #### 一、引言 随着数控技术的持续进步,尤其是开放式数控系统的广泛应用,软件层面的设计在数控领域占据了核心地位。G代码作为数控机床编程的基础语言,在自动化生产流程中发挥着不可或缺的作用。本文的核心内容是关于一个基于Linux平台、采用C语言开发的G代码解释程序的设计思路及其具体实现。 #### 二、G代码解释器概述 **1. 设计背景** - 当前数控技术发展的主要方向是开放式数控系统,这类系统具备出色的可扩展能力、良好的移植性、高度的互换性以及优异的互操作性等优势。 - 计算机硬件技术的快速发展使得在PC平台上构建数控系统成为可能,进而推动了全软件式数控系统的普及。 **2. G代码解释器的重要性** - G代码解释器在全软件式数控系统中是至关重要的组成部分,其主要职责是将G代码转化为数控系统能够识别的数据格式。 - 为了提升数控系统的开放程度,G代码解释器的设计必须兼顾开放性和灵活性。 #### 三、G代码解释器设计与实现 **1. 总体结构设计** - G代码解释器主要由两个核心部分构成:G代码关键字函数表(GKFT)和G代码分组(GG)。 - GKFT用于解析G代码中的关键字,它是解释器的核心骨架;而GG则是语法检查的基础框架。 **2. G代码关键字函数表(GKFT)** - GKFT是一种专门用于存储G代码关键字及其关联处理函数的数据结构。 - 解释器通过查询GKFT,能够根据特定的G代码关键字调用相应的处理函数,从而完成对G代码的有效解析。 - 此种设计方法不仅简化了解释器的构建过程,同时也增强了其可扩展性,因为新增功能...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值