linuxC高级_day5(完结)

news2024/10/11 22:40:23

目录

指针函数

1.概念

2.定义格式

3.函数内开辟空间

函数指针

1.概念

2.定义格式

2.1 格式

3.函数指针数组

3.1 概念

3.2 格式

3.3 赋值

条件编译

1.根据宏是否定义

根据宏值

3.防止头文件重复包含


指针函数

1.概念

本质是函数,函数返回值是指针。类比着指针数组。

指针数组:本质是数组,数组中每个元素是指针。

指针数组定义格式:数据类型 *数组名[元素个数];

int *arr[3];

2.定义格式

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

{

函数体;

return 地址; //当失败时一般返回NULL

}

3.函数内开辟空间

案例一:

#include <stdio.h>

char *fun()
{
    char buf[32] = "hello";

    return buf;
}

int main(int argc, char const *argv[])
{
    char *p = fun();
    printf("%s\n", p);

    return 0;
}

结果未知,因为返回局部变量地址,函数调用结束后没有权限使用栈区的空间了所以结果是不可控的。如果被其他进程占用,可能会报段错误或者打印奇怪的东西。

修改:可以返回堆区的地址

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *fun()
{
    char *buf = (char *)malloc(32);
    if (NULL == buf)
    {
        printf("malloc lost!\n");
        return NULL;
    }
    strcpy(buf, "hello");

    return buf;
}

int main(int argc, char const *argv[])
{
    char *p = fun();
    if (NULL == p)
        printf("fun err!\n");
    printf("%s\n", p);

    return 0;
}
 
   

案例二:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void create_space(char *p) //p=NULL
{
    p = (char *)malloc(32); //改变p的指向,让p指向开辟的堆区
    if (NULL == p)
        printf("malloc err");

    strcpy(p, "hello");
}

int main(int argc, char const *argv[])
{
    char *q = NULL;

    create_space(q); //函数调用后,q依然指向NULL
    //因为p和 q是两个空间,改变函数内的p是不影响函数外的q
    printf("%s\n", q);

    return 0;
}

报段错误:因为q指向NULL, 函数内改变形参p的指向不会影响到q,q还是指向NULL。

修改:传递二级指针

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void create_space(char **p)  //p=&q
{
    *p = (char *)malloc(32);   //*p = *&q = q
    if (NULL == *p)
        printf("malloc err");

    strcpy(*p, "hello");
}

int main(int argc, char const *argv[])
{
    char *q = NULL;

    create_space(&q);   
    //调用函数后,q指向函数内开辟的堆区。因为函数内通过传递q的地址找到q, 让q真的指向开辟的堆区了。
    printf("%s\n", q);

    return 0;
}

进一步理解:

案例三:数组传递

#include <stdio.h>

void fun(int arr[5]) //arr类型是int *
{
    arr[0] = 100;
    printf("%ld\n", sizeof(arr));
}

int main(int argc, char const *argv[])
{
    int a[5] = {1, 2, 3, 4, 5};
    fun(a);
    printf("%d\n", a[0]);

    return 0;
}

传递数组的形式是为了让用户知道要传递的是一个数组,但本质还是传递数组的首地址,也就是传递指针。

函数指针

1.概念

本质是指针,指向了函数。 类比着数组指针。

数组指针:本质指针,指向了数组。

数组指针定义格式:数据类型 (*指针名)[列数];

int a[2][3];

int (*p)[3]=a;

2.定义格式

2.1 格式

数据类型 (*指针名)(参数列表);

函数名:函数首地址

#include <stdio.h>
int add(int a, int b) //add函数名:函数的地址
{
    return a + b;
}

int sub(int a, int b) //sub类型: int (*) (int,int)
{
    return a - b;
}

int main(int argc, char const *argv[])
{
    int (*p)(int, int); //定义了函数指针
    p = add;            //让函数指针p指向add函数

    printf("%d\n", add(1, 2)); //通过函数名直接调用函数
    printf("%d\n", p(1, 2));   //通过函数指针间接调用所指的函数

    p = sub;
    printf("%d\n", sub(1, 2)); //通过函数名直接调用函数
    printf("%d\n", p(1, 2));   //通过函数指针间接调用所指的函数

    return 0;
}

把函数指针当成参数传递给函数。

一种接口,多种方法。

#include <stdio.h>
int add(int a, int b)
{
    return a + b;
}

int sub(int a, int b)
{
    return a - b;
}

int test(int (*p)(int, int), int a, int b)  //p=add, a=1, b=2;     p=sub,a=1,b=2
{
    return p(a, b);  //add(1,2);  sub(1,2);
}

int main(int argc, char const *argv[])
{
    printf("%d\n", test(add, 1, 2));
    printf("%d\n", test(sub, 1, 2));

    return 0;
}

结构体内成员是函数指针(不常用但是看内核原码的使用可能会见到)

#include <stdio.h>
struct test
{
    int (*p)(int, int);
};

int add(int a, int b)
{
    return a + b;
}

int main(int argc, char const *argv[])
{
    struct test t;
    t.p = add;

    printf("%d\n", t.p(1, 2));

    return 0;
}

3.函数指针数组

3.1 概念

本质是数组,数组中元素是函数指针。

3.2 格式

数据类型 (*数组名[元素个数])(形参列表);

数据类型:和函数指针指向的函数的返回值一致

形参列表:和函数指针指向的函数参数一致

3.3 赋值

int (*arr[3])(int,int) = {函数名};

#include <stdio.h>

int add(int a, int b)
{
    return a + b;
}

int sub(int a, int b)
{
    return a - b;
}

int main(int argc, char const *argv[])
{
    int (*arr[2])(int, int) = {add, sub};   //函数指针数组

    printf("%d\n", arr[0](1, 2)); //add(1,2);
    printf("%d\n", arr[1](1, 2)); //sub(1,2);

    return 0;
}

练习:

a) 一个整型数

int a;

b) 一个指向整型的指针

int *p=&a;

c)一个指向指针的指针,它指向的指针是一个指向一个整型数

int a;

int *p=&a;

in **q=&p;

d)一个有10个整型数的数组

int a[10];

e)一个有10个指针的数组,该指针是指向一个整型数的

int *arr[10];

f)一个指向有10个整型数数组的指针

int a[1][10]

int (*p)[10]=a;

或者

int arr[10];

p = &arr; //相当于升级,把列地址arr升级为行地址

g)一个指向函数的指针, 该函数有一个整型参数并返回一个整型数

int (*p)(int);

h)一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数

int (*a[10])(int);

条件编译

​​​​​​​

按照条件是否满足决定代码是否被编译,是预处理指令。

简单来说就是 后面的条件语句(condition)如果执行结果不为0,则该#if语句块内的代码会被编译,否则就不会被编译。

1.根据宏是否定义

#define 宏名

#ifdef 宏名

代码块1

#else

代码块2

#endif

执行顺序:如果宏定义了则编译代码块1,否则编译代码块2

根据宏值

#define 宏名 值

#if 宏名

代码块1

#else

代码块2

#endif

执行顺序:宏的值为非0也就是真则编译代码块1,否则编译代码块2

3.防止头文件重复包含

放在头文件中:

#ifndef 宏名

#define 宏名

头文件中语句

#endif

报错结构体stu重复定义,因为head.h被多次引用,而其中定义了结构体stu所以结构体重复定义了。

修改:加上防止头文件重复包含

编译通过

练习:

笔试题一套:

嵌入式工程师笔试题-CSDN博客

总结与回顾

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

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

相关文章

C++系统教程004-数据类型(03)

一 .变量 变量是指在程序运行期间其值可以发生改变的量。每个变量都必须有一个名称作为唯一的标识&#xff0c;且具有一个特定的数据类型。变量使用之前&#xff0c;一定要先进行声明或定义。 1.变量的声明和定义 C中&#xff0c;变量声明是指为变量提供一个名称&#xff0c…

鸢尾花书实践和知识记录[6-23数据聚类]

文章目录 思维导图数据聚类和引例基于图论的聚类算法算法流程1构造数据构造距离矩阵相似度相似度矩阵创建图 拉普拉斯矩阵标准拉普拉斯矩阵(Combinatorial Laplacian)归一化拉普拉斯矩阵 (Normalized Laplacian)无标度拉普拉斯矩阵 (Signless Laplacian)归一化对称拉普拉斯矩阵…

这么好看的桌面时钟 怎么能不分享给大家

最近小编发现了非常好用的桌面时钟。桌面时钟顾名思义就是可以放在桌面上的时钟&#xff0c;这是一款界面优美,功能实用,易于操作的桌面时钟工具芝麻时钟&#xff08;下载地址&#xff1a;https://clock.zhimasoft.cn/&#xff09;。 1、首先来看下这些时钟的效果&#xff0c;…

Ping32企业加密软件:保护数据安全

在数字化时代&#xff0c;数据安全已成为每个企业不可忽视的重要课题。无论是客户信息、财务报表&#xff0c;还是商业机密&#xff0c;数据的安全性直接关系到企业的声誉与运营。为了应对不断变化的安全威胁&#xff0c;选择一款可靠的企业加密软件尤为重要。在这里&#xff0…

MFC的.rc 和.rc2文件【常见问题】

目录 一、介绍 .rc 文件 .rc2 文件 使用上的建议 二、实例 工程截图 rc文件 rc2文件 注意&#xff1a; 三、使用 能否删除&#xff1f; 一、介绍 在MFC项目中&#xff0c;.rc和.rc2文件都是资源脚本文件&#xff0c;但它们有不同的用途和管理方式。它们两指向的是同…

VS2022使用技巧

目录 如何打开资源管理器如何打开监视窗口 如何打开资源管理器 如何打开监视窗口 前提:必须先按f10 开始调试起来了

Typora+PicGo实现自动上传图片至图床

文章目录 前言图床选择图床去不图床 配置PicGo安装Typora对象存储七牛云又拍云 前言 使用过Typora的小伙伴应该已经发现&#xff0c;若是想分享给别人看不但需要发送md文件&#xff0c;还需要把对应的图片一起发给对方&#xff0c;否则图片无法显示。 但是每次都要打个压缩包发…

USIM 卡的鉴权原理

USIM 卡的一个重要功能是用来做鉴权。鉴权是移动通信中非常重要的概念&#xff0c;具体的实现需要很复杂的算法。 鉴权&#xff1a;就是鉴定你是否拥有访问网络的权利。用户在开卡后&#xff0c;手机的 USIM 卡里和运营商的核心网中都将存储一个密钥&#xff0c;或者说一个密码…

进程同步问题

在操作系统中引入进程后&#xff0c;一方面系统中多道程序可以并发进行&#xff0c;有效的改善了资源利用率&#xff0c;提高了系统的吞吐量。但另一方面&#xff0c;系统变得更加复杂了&#xff0c;如果不能通过有效措施对多个进程进行有效管理&#xff0c;那么必然会因为这些…

关于mac下的nvm设置淘宝镜像源

1. 进入配置文件修改镜像源 vim ~/.bash_profile增加下面内容 export NVM_NODEJS_ORG_MIRRORhttps://npmmirror.com/mirrors/node/2. 查看远程node镜像 nvm ls-remote3. 下载镜像 nvm install 14.17.64. 使用镜像 nvm use 14.17.6

Windows系统编程 - 目录操作、磁盘、卷信息

前言 各位师傅大家好&#xff0c;我是qmx_07&#xff0c;今天继续讲解Windows系统编程的相关知识:目录操作 目录 目录操作 创建目录 通过CreateDirectory函数创建目录 原型: BOOL CreateDirectoryA([in] LPCSTR lpPathName,//目录名称[in, opt…

ORA-01031 权限不足

目录 1. 问题描述2. 问题解决 1. 问题描述 通过PL/SQL客户端&#xff0c;使用scott账户登录后&#xff0c;创建用户时&#xff0c;提示ORA-01031. 2. 问题解决 通过 cmd sqlplus进入Oracle 通过system&#xff08;密码manager&#xff09;登录 要授权的是scott账户 gran…

Flutter包管理(三)

1、作用 在APP的实际开发过程中往往会依赖很多包&#xff0c;而这些包之间存在着交叉依赖、版本依赖&#xff0c;由开发者自己管理手动管理会非常麻烦&#xff0c;每种开发生态或编程官方会提供一些包的管理工具&#xff0c;在Flutter中我们在pubspec.yaml文件中来管理第三方依…

msvcp140.dll丢失的5个解决方法,全面解读msvcp140.dll丢失问题

msvcp140.dll文件的丢失可能会引发一系列潜在问题并对计算机系统产生多方面的影响。首先&#xff0c;这个文件是Microsoft Visual C Redistributable Package的一部分&#xff0c;对于许多基于Windows的应用程序运行至关重要。一旦丢失&#xff0c;可能会导致部分软件无法正常启…

【AI系统】AI系统的组成

AI系统的组成是实现其设计目标的基础。本文将详细介绍AI系统的各个组成部分&#xff0c;以及它们如何协同工作以支持AI应用程序的开发和运行。 I. 引言 AI系统的复杂性要求其组成不仅要关注单一的硬件或软件&#xff0c;而是需要一个多层次、多维度的架构设计。这包括从应用与…

JavaWeb三大组件之Servlet

1. Servlet 一、Servlet介绍 1、概念 Servlet&#xff08;Server Applet&#xff09;是Java Servlet的简称&#xff0c;称为小服务程序或服务连接器&#xff0c;用Java编写的服务器端程序&#xff0c;具有独立于平台和协议的特性&#xff0c;主要功能在于交互式地浏览和生成…

链表(3)_重排链表_面试题

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 链表(3)_重排链表_面试题 收录于专栏【经典算法练习】 本专栏旨在分享学习算法的一点学习笔记&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目录 1. 题…

Word排版 | 如何文字部分固定行距、图片(嵌入型)单倍行距

问题描述 在写一个要求比较高的项目报告&#xff0c;总共有109页 89张图片&#xff0c;而且必须用word写 因此&#xff1a; 文字部分需要固定行距23磅图片部分需要单倍行距&#xff08;不然无法使用嵌入式&#xff09; 难点 文字和图片难以有效分离&#xff0c;无法分别设…

Redis分布式锁-秒杀类锁不住及各种因为锁导致的“血案”现场全侦破代码详解

背景 继上文“详解Redis分布式锁在SpringBoot的Async方法中没锁住的坑”不少读者发觉用了我的方法还是在并发的情况下有锁不住&#xff01; 于是我和几个没有锁住的读者了解了它们的场景&#xff0c;才知道他们在认知上存在几个误区&#xff0c;同时也发现这一块内容、知识真…

【Docker】06-DockerCompose

1. Docker compose 2. Docker Compose部署项目 docker-compose.yml version: "3.8"services:mysql:image: mysqlcontainer_name: mysqlports:- "3307:3306"environment:TZ: Asia/ShanghaiMYSQL_ROOT_PASSWORD: 123volumes:- "/root/docker/mysql/…