C语言-指针相关使用

news2024/11/28 15:39:42

指针是 C语言的重要组成部分,是 C语言的核心、精髓。

在 C语言中,指针使用得当,能显著提高某些程序的效率,使用不当,则很容易造成系统错误、

一、指针使用

编译系统为每个变量都分配了一个能满足其类型大小的内存单元地址,访问内存地址就可以找到对应的变量。

我们将变量的地址形象化地称为该变量的指针。即通过指针能访问以它为地址的内存单元,从而获取变量的信息。

变量与指针的关系:

变量的地址是变量和指针之间的连接纽带。所谓指向就是通过地址来体现的。

因为指针通常指向一个变量的地址,所以将一个变量的地址赋给指针后,这个指针就指向了该变量。

一个变量的地址就称为该变量的指针。

1、指针变量

1.1 指针变量的定义

C语言中,指针变量就是专门用来存放内存单元地址的变量类型。即指针类型。

定义指针变量的基本格式为:

datatype *var_name;

其中:

  • datatype:表示该指针变量所指向的变量的数据类型 。
  • *:表示该变量是一个指针变量。
  • var_name:变量名,即为定义的指针变量名。

1.2 指针变量的赋值

指针变量和普通变量一样,使用前需要先进行定义并赋予具体的值,未赋值的指针变量是不能使用的。

注意:指针变量的赋值只能赋予地址,而不能是其他数据,否则将引起错误。

指针变量的赋值方式一般有两种:

// 方式1:定义指针变量的同时进行赋值
int a;
int *p = &a;

// 方式2:先定义指针变量再赋值
int a, *p;
p = &a;

注意:

  • C语言使用 “ & 变量名”表示某个变量的地址。
  • 如果先定义指针变量之后在赋值时,指针变量前不再加“*”号。

1.3 指针变量的引用

引用指针变量是对变量进行间接访问的一种形式,其含义表示引用指针变量所指向的值(变量的值)。

引用指针变量的一般格式为:*指针变量

示例如下:

int main() {
    int a = 18, b = 99, c = 100;
    int *p = &a;  //定义指针变量

    *p = b;  //通过指针变量修改内存上的数据
    c = *p;  //通过指针变量获取内存上的数据
    printf("a=%d, b=%d, c=%d, *p=%d, p=%d\n", a, b, c, *p, p); 
    //输入:a=99, b=99, c=99, *p=99, p=6291020
    
    return 0;
}

2、&与*和&&的区别

&与*都是单目运算符,两者的优先级相同,按照自右向左的方向结合。

  • &:表示取地址运算符,用于返回一个操作数的地址。
  • *:表示指针运算符,用于返回指定地址内保存的变量值。

&&的区别,假设语句如下:

int a, *p, q;
p = &a;
q = *p;

(1)p = &a:是将变量 a的内存地址赋值给了指针变量 p。
(2)q = *p:是将指针 p指向的变量,即变量 a的值赋值给 q。
(3)&*p:先进行 *运行再进行 &运算。*p相当于变量 a,在进行 &运算。所以,&p相当于取变量 a的地址。
(4)
&a:先进行 &运行再进行 *运算。&a就是取变量 a的地址,在进行 运算。所以,&a相当于取变量 a所在地址的值,即变量 a的值。

示例如下:

#include <stdio.h>

int main() {
    int a, *p, q;
    a = 88;
    p = &a;
    q = *p;

    printf("a=%d, &a=%d, p=%d, *p=%d, q=%d\n", a, &a, p, *p, q);
    printf("&*p=%d, *&a=%d\n", &*p, *&a);
    return 0;
}

在这里插入图片描述

二、指针的自增自减运算

指针的自增自减运算是按照它所指向的数据类型的内存长度进行自增或者自减的,

示例如下:

#include <stdio.h>

int main() {
    int i, *pi;
    double d, *pd;

    i = 18;
    d = 12.2;
    pi = &i;
    pd = &d;

    printf("i=%d, &i=%d, pi=%d, *pi=%d,\n", i, &i, pi, *pi);
    printf("pi++之后\n", i, &i, pi, *pi);
    pi++;
    printf("i=%d, &i=%d, pi=%d, *pi=%d,\n", i, &i, pi, *pi); // pi++:pi增加4(int类型的4个字节)

    printf("===============\n");

    printf("d=%E, &d=%d, pd=%d, *pd=%d\n", d, &d, pd, *pd);
    pd++;
    printf("d=%E, &d=%d, pd=%d, *pd=%d\n", d, &d, pd, *pd); // pd++:pd增加2(double类型的8个字节)

    return 0;
}

在这里插入图片描述

三、指向指针的指针

一个指针可以指向整型变量、实型变量、字符型变量,也可以指向另一个指针,此时称其为指向指针的指针。

指向指针的指针一般格式如下:datatype **pointer_name;

其中:

  • datatype:表示该指针变量所指向另一个指针变量的变量的数据类型 。
  • **p:表示指针变量 p指向了另一个指针变量。比如:int **p; 就相当于 int *(*P); 。

示例如下:

#include <stdio.h>

int main() {
    int i;
    char **p;
    char *a[] = {
            "周一",
            "周二",
            "周三",
            "周四",
            "周五",
            "周六",
            "周日"
    };

    for (i = 0; i < 7; i++) {
        p = a + i;    //将数据个元素的地址赋值为 p
        printf("%s  ", *p);
    }

    return 0;
}

在这里插入图片描述

四、指针变量做函数中的使用

1、指针变量做函数函数

指针型变量可以作为函数参数使用。

示例如下:

#include <stdio.h>

/* 函数声明 */
void my_swap(int *x, int *y);

int main() {
    /* 局部变量定义 */
    int a = 100;
    int b = 200;

    printf("交换前,a 的值: %d\n", a);
    printf("交换前,b 的值: %d\n", b);

    /* 调用函数来交换值
      &a 表示指向 a 的指针,即变量 a 的地址
      &b 表示指向 b 的指针,即变量 b 的地址
    */
    my_swap(&a, &b);
    printf("交换后,a 的值: %d\n", a);
    printf("交换后,b 的值: %d\n", b);

    return 0;
}

/* 函数定义 */
void my_swap(int *x, int *y) {
    int temp;
    temp = *x;    /* 保存地址 x 的值 */
    *x = *y;      /* 把 y 赋值给 x */
    *y = temp;    /* 把 temp 赋值给 y */
    return;
}

通过指针传递参数时,传递的是变量的地址,此时地址内存存放的数据会发生改变的。

在这里插入图片描述

2、指针变量做函数返回值

返回指针值的函数简称为指针函数。

定义指针函数的一般格式为:函数名迁安加一个 “*” 修饰。

return_dataType *function_name( parameter list )
{
    int *p;
   //body of the function
    
   return  p; 
}

示例如下:

#include <stdio.h>

// 声明指针函数
int *f_acreage(int a, int b);

int acreage;

int main() {
    int a, b, *p_res;
    a = 11;
    b = 5;

    p_res = f_acreage(a, b);

    printf("p_res值 = %d\n", *p_res);
    printf("acreage值 = %d\n", acreage);

    return 0;
}

// 定义指针函数
int *f_acreage(int a, int b) {
    int *p;
    p = &acreage;
    acreage = (a + b) * 2;
    return p; // 返回指针
}

在这里插入图片描述

五、指针数组做 main函数的参数

main函数是所有程序运行时的入口,有系统调用,当处于操作命令状态下时,输入 main所在的文件名,即可调用 main函数。同时我们也可以给 main函数传值。

main函数的有参格式为:int main(int argc, char *argv[])

通过操作系统的命令行调用执行文件时,就可以给 main函数传值。

命令行的一般格式为:filename.exe 参数1 参数3 … 参数n

可执行文件名与和其后面的参数之间必须使用空格分隔。

示例如下:

#include <stdio.h>

int main(int argc, char *argv[]) {
    int loc, ser;

    printf("he argument list for the main function: \n");
    printf("Command nam: %s\n", *argv);
    printf("Parameter numbe: %d\n", argc);

    for (int i = 0; i < argc; i++) {
        printf("argv[%d] = %s\n", i, argv[i]);
    }
    return 0;
}

在这里插入图片描述

– 求知若饥,虚心若愚。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1096417.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vqvae简单实战,利用vqvae来提升模型向量表达

最近CV领域各种大模型在图像生成领域大发异彩&#xff0c;比如这两年大火的dalle系列模型。在这些模型中用到一个基础模型vqvae&#xff0c;今天我们写个简单实现来了解一下vqvae的工作原理。vqvae原始论文连接https://arxiv.org/pdf/1711.00937.pdf 1&#xff0c;代码 首先我们…

机器学习——奇异值分解二(特征分解+SVD纯理解)

矩阵的特征分解 特征值和特征向量的定义 抄来的&#xff1a;奇异值分解 困惑1&#xff1a;特征值和特征向量&#xff0c;和原矩阵是怎样的关系&#xff0c;需要一个栗子进行更具象的认识 困惑2&#xff1a;为什么多个特征向量组合成的矩阵&#xff0c;可以构成矩阵A的特征分解…

项目管理之实施关键步骤

项目管理已成为当代企业运营和发展过程中不可或缺的重要环节。如何实现高效、有序和可控的项目管理&#xff0c;一直是企业领导和项目团队追求的目标。本文将结合项目管理七招制胜内容&#xff0c;详细阐述项目管理实战中的具体做法。 如何分析项目 了解项目的背景和目的&…

网工记背配置命令(3)----POE配置示例

POE 供电就是通过以太网供电&#xff0c;这种方式仅凭借那根连接通信终端的网线就可完成为它们供电。POE提供的是-53V~0v 的直流电&#xff0c;供电距离最长可达 100m。PoE 款型的交换机的软件大包天然支持 POE&#xff0c;无需 license&#xff0c;通过执行 poe-enable 命令使…

【力扣1844】将所有数字用字符替换

&#x1f451;专栏内容&#xff1a;力扣刷题⛪个人主页&#xff1a;子夜的星的主页&#x1f495;座右铭&#xff1a;前路未远&#xff0c;步履不停 目录 一、题目描述二、题目分析 一、题目描述 给你一个下标从 0 开始的字符串 s &#xff0c;它的偶数下标处为小写英文字母&am…

系列七、Redis持久化

一、是什么 将内存中的数据写入到硬盘的过程。 二、持久化方式 RDB、AOF 2.1、RDB&#xff08;Redis Database&#xff09; 2.1.1、概述 在指定的时间间隔&#xff0c;执行数据集的时间点快照。实现类似照片记录效果的方式&#xff0c;就是把某一时刻的数据和状态以文件的形…

vue3后台管理框架之收获

前端⼯程化概念 在学VUE和webpack打包的时候&#xff0c;了解到前端⼯程的基本概念&#xff0c;如下&#xff1a; 实际的前端开发&#xff0c;遵循四个现代化&#xff1a; 1.模块化&#xff08;js的模块化、css的模块化、其他资源的模块化&#xff09; 2.组件化&#xff08;复⽤…

05-React组件的组合使用

05-React组件的组合使用 1.TodoList案例 需求&#xff1a;TodoList组件化实现此功能 显示所有todo列表输入文本, 点击按钮显示到列表的首位, 并清除输入的文本 1).实现&#xff1a; 完成TodoList组件的静态页面以及拆解组件 动态初始化列表 //App.jsx export default class …

[初始java]——java为什么这么火,java如何实现跨平台、什么是JDK/JRE/JVM

java的名言&#xff1a; ”一次编译、到处运行“ 一、编译语言与解释语言 编译&#xff1a; 是将整份源代码转换成机器码再进行下面的操作&#xff0c;最终形成可执行文件 解释&#xff1a; 是将源代码逐行转换成机器码并直接执行的过程&#xff0c;不需要生成目标文件 jav…

10.14~10.15verilog操作流程与Block Design

后面的那个是延时精度 verilog文件结构 文件名称与写的模板没有关系&#xff0c;这个文件名为P1,但模板名为andgate 但是如果是仿真文件&#xff0c;就需要开头的模板名和仿真文件名相同 .v是源文件&#xff0c;设计文件 .v在设计与sim里都有&#xff0c;静态共享&#xff0…

卡顿分析与布局优化

卡顿分析与布局优化 大多数用户感知到的卡顿等性能问题的最主要根源都是因为渲染性能。Android系统每隔大概16.6ms发出VSYNC信 号&#xff0c;触发对UI进行渲染&#xff0c;如果每次渲染都成功&#xff0c;这样就能够达到流畅的画面所需要的60fps&#xff0c;为了能够实现60fp…

CISA 彻底改变了恶意软件信息共享:网络安全的突破

在现代网络安全中&#xff0c;战术技术和程序&#xff08;TTP&#xff09;的共享对于防范网络事件至关重要。 因此&#xff0c;了解攻击向量和攻击类型之间的关联如今是让其他公司从其他公司遭受的 IT 事件中受益&#xff08;吸取经验教训&#xff09;的重要一步。 美国主要网…

多模态大模型升级:LLaVA→LLaVA-1.5,MiniGPT4→MiniGPT5

Overview LLaVA-1.5总览摘要1.引言2.背景3.LLaVA的改进4.讨论附录 LLaVA-1.5 总览 题目: Improved Baselines with Visual Instruction Tuning 机构&#xff1a;威斯康星大学麦迪逊分校&#xff0c;微软 论文: https://arxiv.org/pdf/2310.03744.pdf 代码: https://llava-vl.…

无法解析符号 ‘SpringBootApplication’

刚打开一个项目出现"SpringBootApplication"无法解析&#xff1a; 通过以下步骤&#xff0c;修改maven路径即可&#xff1a; 文件---->设置&#xff08;File--->Settings&#xff09; 构建、执行、部署--->构建工具--->Maven--->Maven主路经&#xf…

07-ConfigurationClassPostProces的解析

文章目录 如何解析Component,Service,Configurationd,Bean,Import等注解1. 源码描述2. 类继承结构图3. 解析流程4. 具体的注解解析 如何解析Component,Service,Configurationd,Bean,Import等注解 1. 源码描述 BeanFactoryPostProcessor used for bootstrapping processing of…

论文笔记[156]PARAFAC. tutorial and applications

原文下载&#xff1a;https://www.sciencedirect.com/science/article/abs/pii/S0169743997000324 摘要 本文介绍了PARAFAC的多维分解方法及其在化学计量学中的应用。PARAFAC是PCA对高阶数组的推广&#xff0c;但该方法的一些特性与普通的二维情况截然不同。例如&#xff0c;…

O2O优惠券预测

O2O优惠券预测 赛题理解赛题类型解题思路 数据探索理论知识数据可视化分布 特征工程赛题特征工程思路 模型训练与验证 赛题理解 赛题类型 本赛题要求提交的结果是预测15 天内用券的概率&#xff0c;这是一个连续值&#xff0c;但是因为用券只有用与不用两种情况&#xff0c;而…

IDEA中为Maven配置使用vpn工具连接的网络

IDEA中为Maven配置使用vpn工具连接的网络 在电脑上使用VPN工具连接上特定网络后&#xff0c;发现idea中使用maven工具还是无法访问相关的网络&#xff0c;这时需要在idea中进行相关配置&#xff0c;开启ipv4代理 -Djava.net.preferIPv4Stacktrue maven配置 这时&#xff0c;…

JavaScript基础知识13——运算符:一元运算符,二元运算符

哈喽&#xff0c;大家好&#xff0c;我是雷工。 JavaScript的运算符可以根据所需表达式的个数&#xff0c;分为一元运算符、二元运算符、三元运算符。 一、一元运算符 1、一元运算符&#xff1a;只需要一个表达式就可以运算的运算符。 示例&#xff1a;正负号 一元运算符有两…

Golang 协程 与 Java 线程池的联系

Golang 协程 与 Java 线程池的联系 引言Java 线程池缺陷Golang 协程实现思路0.x 版本1.0 版本1.1 版本Goroutine 抢占式执行基于信号的抢占式调度 队列轮转系统调用工作量窃取GOMAXPROCS设置对性能的影响 小结 引言 如何理解Golang的协程&#xff0c;我觉得可以用一句话概括: …