C语言结构体漫谈:从平凡中见不平凡

大家好,这里是小编的博客频道
小编的博客:就爱学编程

很高兴在CSDN这个大家庭与大家相识,希望能在这里与大家共同进步,共同收获更好的自己!!!

本文目录

  • 引言
  • 正文
  • 《1》 结构体的两种声明
      • 一、结构体的定义
      • 二、全局结构体变量
      • 三、局部结构体变量
      • 四、匿名结构体与全局/局部变量
  • 《2》typedef对结构体类型进行重命名
      • 一、基本语法
      • 二、作用与优势
      • 三、示例说明
  • 《3》 结构体的初始化和访问
      • 1. 声明时初始化
      • 2. **后续初始化**
      • 3.访问结构体成员
  • 《4》 结构体的内存对齐和修改默认对其数的方法
      • 一、结构体与内存对齐的基本概念
      • 二、结构体内存对齐的规则
      • 三、为什么存在内存对齐
      • 四、如何修改默认对齐数
        • 1.使用#pragma pack
        • 2.使用__attribute__((packed))
  • 《5》结构体传参
      • 一、通过值传递结构体
      • 二、通过指针传递结构体
      • 三、返回结构体
        • 3.1 返回结构体值
        • 3.2 返回结构体指针
  • 快乐的时光总是短暂,咱们下篇博文再见啦!!!不要忘了,给小编点点赞和收藏支持一下,在此非常感谢!!!

引言

在C语言中,结构体(struct)是一种用户自定义的数据类型,它允许将多个不同类型的数据项组合成一个单一的类型。结构体是编程中组织相关数据的有效方式,尤其在处理复杂数据时显得尤为重要。以下是对C语言结构体基础知识的详细介绍,一起来看看吧!!

在这里插入图片描述


那接下来就让我们开始遨游在知识的海洋!

正文


在C语言中,当结构体被定义后,可以在全局作用域或局部作用域(如函数内部)中声明其变量。这些结构体变量的作用域和生命周期会根据它们是在全局还是局部声明的而有所不同。下面小编将详细解释全局变量、局部变量以及匿名声明与结构体之间的关系,特别是在主函数内的区别。

《1》 结构体的两种声明


一、结构体的定义

首先,我们需要定义一个结构体。例如:

struct MyStruct {int a;float b;
};

这里我们定义了一个名为MyStruct的结构体,它包含两个成员:一个整型a和一个浮点型b


二、全局结构体变量

如果在所有函数之外声明一个结构体变量,那么它就是全局的。全局结构体变量在整个程序的生命周期内都有效,并且可以被任何函数访问。例如:

// 全局作用域中声明结构体变量
struct MyStruct globalVar;int main() {// 可以在main函数中访问globalVarglobalVar.a = 10;globalVar.b = 3.14;// ... 其他代码
}

在这个例子中,globalVar是一个全局结构体变量,它在整个程序中都是可见的,包括在main函数内。


三、局部结构体变量

如果在某个函数内部声明一个结构体变量,那么它就是局部的。局部结构体变量只在声明它的函数内部有效,一旦函数执行完毕,该变量就会被销毁。例如:

int main() {// 局部作用域中声明结构体变量struct MyStruct localVar;localVar.a = 20;localVar.b = 6.28;// localVar只能在main函数内部使用// ... 其他代码
}

在这个例子中,localVar是一个局部结构体变量,它只能在main函数内部被访问和使用。


四、匿名结构体与全局/局部变量

在C语言中,还可以声明匿名结构体变量。匿名结构体是没有名称的结构体类型,通常用于只需要一个结构体实例的情况。匿名结构体变量的声明方式与全局或局部变量类似,只是没有给出结构体的名称。例如:

// 在全局作用域中声明匿名结构体变量
struct {int x;int y;
} globalAnonymousVar;int main() {// 在局部作用域中声明另一个匿名结构体变量(注意:这是另一个不同的类型)struct {int m;int n;} localAnonymousVar;globalAnonymousVar.x = 1;globalAnonymousVar.y = 2;localAnonymousVar.m = 3;localAnonymousVar.n = 4;// 注意:globalAnonymousVar和localAnonymousVar是不同类型的变量// 因此不能相互赋值或比较// ... 其他代码
}

在这个例子中,globalAnonymousVarlocalAnonymousVar分别是全局和局部的匿名结构体变量。需要注意的是,由于它们是匿名的且定义不同,因此它们是两种完全不同的类型,不能相互赋值或比较。

  • 全局结构体变量在整个程序生命周期内有效,可以被任何函数访问。
  • 局部结构体变量只在声明它的函数内部有效,函数执行完毕后会被销毁。
  • 匿名结构体变量没有名称的结构体类型,通常用于单个实例的情况。全局和局部的匿名结构体变量是两种不同的类型。

希望以上内容能够帮助宝子们理解C语言中结构体与全局变量、局部变量以及匿名声明之间的关系。


typedef是C语言中的一个关键字,它主要用于为数据类型定义新的名称(别名),这包括基本数据类型、引用类型以及自定义的数据类型。在结构体(struct)的使用中,typedef的作用尤为显著,因为它可以简化结构体的声明和使用,提高代码的可读性和可维护性。以下是对typedef对结构体进行重命名的详细介绍.

《2》typedef对结构体类型进行重命名


一、基本语法

typedef的基本语法如下:

typedef 原有类型 新类型名;

当用于结构体时,可以这样写:

typedef struct {成员列表;
} 新类型名;

或者先定义结构体,再用typedef为其命名:

struct 旧类型名 {成员列表;
};
typedef struct 旧类型名 新类型名;

二、作用与优势

  1. 简化声明:使用typedef可以为复杂的结构体类型定义一个简短且易于理解的新名字,从而简化变量的声明。例如,对于包含多个成员的结构体,直接使用其原始类型声明变量可能会显得冗长,而使用typedef定义的新类型名则可以使声明更加简洁明了。
  1. 提高可读性:通过为结构体类型定义具有描述性的新名字,可以提高代码的可读性。这些新名字通常能够更直观地反映结构体的用途或内容,从而使代码更容易被理解和维护。
  1. 便于修改:如果需要在程序中更改结构体的定义,只需修改结构体本身的定义即可,而不必修改所有使用该结构体的变量声明。这是因为这些变量声明使用的是由typedef定义的新类型名,而不是结构体的原始类型名。因此,使用typedef可以降低因修改结构体定义而导致的代码修改量。

三、示例说明

以下是一个使用typedef对结构体进行重命名的示例:

#include <stdio.h>// 使用typedef定义一个新的结构体类型Point3D
typedef struct {int x;int y;int z;
} Point3D;int main() {// 使用新类型名Point3D声明变量pPoint3D p = {1, 2, 3};// 打印变量p的成员值printf("x: %d, y: %d, z: %d
", p.x, p.y, p.z);return 0;
}

在这个示例中,我们首先使用typedef定义了一个新的结构体类型Point3D,该结构体包含三个整型成员xyz。然后,我们在main函数中使用新类型名Point3D声明了一个变量p,并初始化了它的成员值。最后,我们打印了变量p的成员值以验证其正确性。

注意:

  1. 在使用typedef对结构体进行重命名时,应确保新类型名的唯一性和描述性,以避免与其他类型名冲突并提高代码的可读性。
  1. 如果结构体中包含指向自身的指针成员(即自引用),则需要特别注意typedef的使用方式。在这种情况下,可以先定义结构体的匿名类型,然后使用typedef为该类型命名;或者在定义结构体的同时直接使用typedef为其命名,并在结构体内部使用struct关键字加上新类型名来声明指向自身的指针成员。

综上所述:

  • typedef是C语言中一个非常有用的关键字,它可以极大地简化结构体的声明和使用,提高代码的可读性和可维护性。

当然!在C语言中,结构体(struct)是一种用户自定义的数据类型,允许将不同类型的数据组合成一个单一的类型。链表是一种常见的数据结构,它由一系列节点组成,每个节点包含数据部分和指向下一个节点的指针。通过结构体,我们可以方便地实现链表。

下面是一篇关于如何使用C语言的结构体来实现链表的详细介绍。

《3》 结构体的初始化和访问


1. 声明时初始化

我们可以在声明结构体变量的同时对其进行初始化。这通常使用花括号{}来指定每个成员的初值。

struct Student student1 = {"Alice", 20, 95.5};

在这个例子中,我们创建了一个名为student1Student结构体变量,并在声明时将其成员初始化为"Alice"2095.5


2. 后续初始化

如果我们在声明时没有初始化结构体变量,那么可以在后续的代码中逐个设置其成员的值。

struct Student student2;
strcpy(student2.name, "Bob");  // 使用strcpy函数复制字符串到字符数组
student2.age = 22;
student2.grade = 88.0;

注意:

  • 对于字符数组类型的成员,我们不能直接赋值(如student2.name = "Bob";),因为这样会尝试将一个字符串常量的地址赋给字符数组,而不是将字符串内容复制到数组中。因此,我们使用strcpy函数来复制字符串。

3.访问结构体成员

一旦我们有了结构体变量,就可以通过点运算符.来访问其成员。以下是一些示例:

printf("Name: %s
", student1.name);
printf("Age: %d
", student1.age);
printf("Grade: %.2f
", student1.grade);

在这个例子中,我们使用点运算符.来访问student1的各个成员,并将它们打印到控制台上。


《4》 结构体的内存对齐和修改默认对其数的方法

以下是一篇关于结构体的内存对齐和修改默认对齐方法的详细介绍.


一、结构体与内存对齐的基本概念

在编程中,结构体(Structure)是一种可以存储不同类型数据项的复合数据类型。它是一种用户自定义的数据类型,用于封装一组相关联的不同类型的数据项。结构体是一些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量。

内存对齐是指数据在内存中按照一定的规则进行排列,以提高内存访问的效率。对于结构体来说,内存对齐意味着其成员变量在内存中的地址需要满足特定的对齐要求。这种对齐通常是由编译器自动处理的,但程序员也可以通过特定指令进行修改。


二、结构体内存对齐的规则

  1. 结构体的第一个成员对齐到和结构体变量起始位置偏移量为0的地址处。
  1. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。这个对齐数通常是编译器默认的一个对齐数与该成员大小的较小值。不同的编译器和平台可能有不同的默认对齐数。
  1. 结构体总大小为最大对齐数(结构体中每个成员变量都有一个对齐数,取其中最大的一个)的整数倍。这是为了确保结构体在内存中的布局是紧凑且高效的。
  1. 如果嵌套了结构体的情况,嵌套的结构体成员对齐到自己的成员中最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体中成员的对齐数)的整数倍。

三、为什么存在内存对齐

内存对齐的存在主要有以下几个原因:

  1. 提高内存访问效率:在许多计算机架构中,内存的访问速度是有限的。如果数据在内存中的位置是随机的,那么CPU需要花费额外的时间来寻找数据,这被称为内存访问延迟。然而,如果数据按照特定的对齐规则进行存储,CPU的内存控制器就可以更有效地预取数据,从而减少内存访问延迟。
  1. 提高硬件效率:许多现代CPU都有专门为对齐数据而设计的内部机制。例如,一些CPU具有专门的对齐引擎,可以更快地处理对齐的数据。如果数据没有对齐,CPU可能需要进行多次访问内存才能获取到完整的数据,这会降低CPU的效率。
  1. 减少数据依赖:在某些情况下,如果数据没有对齐,可能会导致一些特定的CPU指令无法使用,从而增加了数据的依赖性。这可能会使得程序的并行度降低,从而影响程序的性能。
  1. 提高程序的稳定性:在某些情况下,不对齐的内存访问可能会导致硬件异常或者程序崩溃。因此,编程时进行内存对齐不仅可以提高程序的性能,还可以提高程序的稳定性和可维护性。

四、如何修改默认对齐数

在C语言中,可以使用#pragma pack__attribute__((packed))来改变结构体的对齐方式以减少填充字节。以下是两种方法的示例:

1.使用#pragma pack
#include <stdio.h>
#include <stddef.h>// 将对齐设置为1字节
#pragma pack(push, 1)
typedef struct {char c1;       // 1 byteint i;         // 4 bytes, but aligned to 1 byte boundary herechar c2;       // 1 byte
} S1;
#pragma pack(pop)  // 恢复默认对齐设置int main() {printf("%zu
", sizeof(S1));  // 输出结果为6,因为没有额外的填充字节return 0;
}

在这个例子中,使用了#pragma pack(push, 1)将当前的对齐设置保存在栈中,并设置新的对齐方式为1字节。这样,结构体S1的成员就会紧密排列在一起,没有额外的填充字节。使用完之后,通过#pragma pack(pop)恢复之前的对齐设置。

2.使用__attribute__((packed))

这种方法适用于GCC和一些兼容的编译器。它告诉编译器不要为结构体的成员进行任何额外的对齐填充。

#include <stdio.h>
#include <stddef.h>typedef struct __attribute__((packed)) {char c1;       // 1 byteint i;         // 4 bytes, but packed tightly with no paddingchar c2;       // 1 byte
} S2;int main() {printf("%zu
", sizeof(S2));  // 输出结果为6,同样没有额外的填充字节return 0;
}

需要注意的是:

  • 虽然这两种方法可以减少结构体的总大小,但它们可能会降低数据访问的效率。因为未对齐的数据访问可能需要更多的内存操作,这在某些平台上可能会有较大的性能影响。

结构体的内存对齐是提高内存访问效率和程序稳定性的重要手段。了解并掌握结构体内存对齐的规则和修改默认对齐数的方法对于优化程序性能和资源利用具有重要意义。在实际编程中,应根据具体需求和平台特性选择合适的对齐方式和策略。


《5》结构体传参

一、通过值传递结构体

最简单的方式是通过值传递结构体到函数中。这意味着函数会接收到结构体的一个副本,对副本的任何修改都不会影响原始结构体。

#include <stdio.h>
#include <string.h>struct Person {char name[50];int age;float height;
};void printPerson(struct Person p) {printf("Name: %s
", p.name);printf("Age: %d
", p.age);printf("Height: %.2f
", p.height);
}int main() {struct Person person1 = {"Alice", 30, 5.7};printPerson(person1); // 通过值传递return 0;
}

缺点

  • 如果结构体很大,通过值传递会导致大量的内存复制操作,从而降低程序效率。

二、通过指针传递结构体

更常见且高效的方法是通过指针传递结构体。这样,函数接收的是指向结构体的指针,可以直接访问和修改原始数据。

#include <stdio.h>
#include <string.h>struct Person {char name[50];int age;float height;
};void printPerson(struct Person *p) {printf("Name: %s
", p->name);printf("Age: %d
", p->age);printf("Height: %.2f
", p->height);
}void modifyPerson(struct Person *p) {strcpy(p->name, "Bob");p->age = 25;p->height = 6.0;
}int main() {struct Person person1 = {"Alice", 30, 5.7};printPerson(&person1); // 通过指针传递modifyPerson(&person1); // 修改结构体内容printPerson(&person1); // 再次打印以查看修改结果return 0;
}

优点

  • 避免了大结构体的复制开销。
  • 可以直接修改原始结构体中的数据。

在某些情况下,你可能希望从函数中返回一个结构体。这同样可以通过值和指针两种方式来实现。

三、返回结构体

3.1 返回结构体值
#include <stdio.h>struct Point {int x;int y;
};struct Point createPoint(int x, int y) {struct Point p;p.x = x;p.y = y;return p;
}int main() {struct Point p1 = createPoint(10, 20);printf("Point created: (%d, %d)
", p1.x, p1.y);return 0;
}

对于小型结构体,这种方式是可行的,但对于大型结构体,返回值可能会导致性能问题,因为涉及到结构体的复制。

3.2 返回结构体指针
#include <stdio.h>
#include <stdlib.h>struct Point {int x;int y;
};struct Point* createPoint(int x, int y) {struct Point *p = (struct Point*)malloc(sizeof(struct Point));if (p != NULL) {p->x = x;p->y = y;}return p;
}int main() {struct Point *p1 = createPoint(10, 20);if (p1 != NULL) {printf("Point created: (%d, %d)
", p1->x, p1->y);free(p1); // 不要忘记释放动态分配的内存}return 0;
}

这种方法适用于大型结构体或需要在函数外部持续使用结构体的情况,但需要注意内存管理,确保在使用完毕后释放动态分配的内存。

  • 通过值传递:简单直观,但不适合大型结构体,因为会有较大的内存开销。
  • 通过指针传递:高效且灵活,可以直接修改原始数据,是推荐的方法。
  • 返回结构体:小型结构体可以通过值返回,大型结构体建议通过指针返回并注意内存管理。

理解并掌握这些结构体传参方式,将有助于宝子们编写更高效、灵活的C语言程序。


快乐的时光总是短暂,咱们下篇博文再见啦!!!不要忘了,给小编点点赞和收藏支持一下,在此非常感谢!!!

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

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

相关文章

深度学习图像算法中的网络架构:Backbone、Neck 和 Head 详解

深度学习已经成为图像识别领域的核心技术&#xff0c;特别是在目标检测、图像分割等任务中&#xff0c;深度神经网络的应用取得了显著进展。在这些任务的网络架构中&#xff0c;通常可以分为三个主要部分&#xff1a;Backbone、Neck 和 Head。这些部分在整个网络中扮演着至关重…

信安大赛单机取证

22年国赛单机取证 Evidence4 先搜索Evidence 找到一个 Evidence4nsOh2.pngf5b9ce3e485314c23c40a89d994b2dc8 Evidence2 之后再一个个找 这个是压缩包格式的 导出来 伪加密 修复一下 Evidence2ZQOo2.jpg9e69763ec7dac69e2c5b07a5955a5868 Evidence3 png的文件 改个宽高 E…

jmeter事务控制器-勾选Generate Parent Sample

1、打开jmeter工具&#xff0c;添加线程组&#xff0c;添加逻辑控制器-事务控制器 2、在事务控制器&#xff0c;勾选Generate parent sample&#xff1a;生成父样本&#xff1b;说明勾选后&#xff0c;事务控制器会作为父节点&#xff0c;其下面的请求作为子节点 3、执行&#…

Flutter插件制作、本地/远程依赖及缓存机制深入剖析(原创-附源码)

Flutter插件在开发Flutter项目的过程中扮演着重要的角色&#xff0c;我们从 ​​​​​​https://pub.dev 上下载添加到项目中的第三方库都是以包或者插件的形式引入到代码中的&#xff0c;这些第三方工具极大的提高了开发效率。 深入的了解插件的制作、发布、工作原理和缓存机…

Linux 服务器挖矿木马防护实战:快速切断、清理与加固20250114

Linux 服务器挖矿木马防护实战&#xff1a;快速切断、清理与加固 引言 挖矿木马作为一种常见的恶意软件&#xff0c;对服务器资源和安全构成严重威胁。据安全机构统计&#xff0c;2023 年全球约 45%的 Linux 服务器遭受过挖矿木马攻击&#xff0c;平均每台被感染服务器每月造…

OpenAI推出首个AI Agent!日常事项自动化处理!

2025 年1月15日&#xff0c;OpenAI 正式宣布推出一项名为Tasks的测试版功能 。 该功能可以根据你的需求内容和时间实现自动化处理。比方说&#xff0c;你可以设置每天早晨 7 点获取天气预报&#xff0c;或定时提醒遛狗等日常事项。 看到这里&#xff0c;有没有一种熟悉的感觉&a…

闪豆多平台视频批量下载器

1. 视频链接获取与解析 首先&#xff0c;在哔哩哔哩网页中随意点击一个视频&#xff0c;比如你最近迷上了一个UP主的美食制作视频&#xff0c;想要下载下来慢慢学。点击视频后&#xff0c;复制视频页面的链接。复制完成后&#xff0c;不要急着关闭浏览器&#xff0c;因为接下来…

卷积神经网络的底层是傅里叶变换

1 卷积神经网络的底层是傅里叶变换&#xff0c;傅里叶变换的底层是希尔伯特空间坐标变换_哔哩哔哩_bilibili 卷积神经网络的底层是傅里叶变换&#xff0c;傅里叶变换的底层是希尔伯特空间坐标变换_哔哩哔哩_bilibili从“卷积”、到“图像卷积操作”、再到“卷积神经网络”&…

攻防世界_SQL注入

inget 尝试万能钥匙。 输入?id1or11# supersqli 1.找注入点 输入框 2.判断字符型&#xff0c;数字型 输入1 and 11 和1 and 12&#xff0c;发现两次提交后页面一样&#xff0c;判断出为字符型注入 3.判断闭合符号 输入1&#xff0c;回显正常 输入1&#xff0c;报错 加上…

怎么把文章发表到网上?在平台上投稿文章会有哪些常见问题?

怎么把文章发表到网上&#xff1f;在发表文章的过程中&#xff0c;我们可能会碰到各种各样的问题。这些问题要么导致发表时间被拖长&#xff0c;要么可能导致文章被拒稿。 就让我们来了解下文章发表过程中需要注意的一些细节&#xff0c;知晓怎么顺利地把文章发表到网上。 一、…

检验统计量与p值笔记

一、背景 以雨量数据为例&#xff0c;当获得一个站点一年的日雨量数据后&#xff0c;我们需要估计该站点的雨量的概率分布情况&#xff0c;因此我们利用有参估计的方式如极大似然法估计得到了假定该随机变量服从某一分布的参数&#xff0c;从而得到该站点的概率密度函数&#x…

【Flink系列】6. Flink中的时间和窗口

6. Flink中的时间和窗口 在批处理统计中&#xff0c;我们可以等待一批数据都到齐后&#xff0c;统一处理。但是在实时处理统计中&#xff0c;我们是来一条就得处理一条&#xff0c;那么我们怎么统计最近一段时间内的数据呢&#xff1f;引入“窗口”。 所谓的“窗口”&#xff…

C#轻松实现条形码二维码生成及识别

一、前言 大家好&#xff01;我是付工。 今天给大家分享一下&#xff0c;如何基于C#来生成并识别条形码或者二维码。 二、ZXing.Net 实现二维码生成的库有很多&#xff0c;我们这里采用的是http://ZXing.Net。 ZXing是一个开放源码的&#xff0c;用Java实现的多种格式的一…

OpenCV实现Kuwahara滤波

Kuwahara滤波是一种非线性的平滑滤波技术&#xff0c;其基本原理在于通过计算图像模板中邻域内的均值和方差&#xff0c;选择图像灰度值较为均匀的区域的均值来替代模板中心像素的灰度值。以下是Kuwahara滤波的详细原理说明&#xff1a; 一、基本思想 Kuwahara滤波的基本思想…

24-25-1-单片机开卷部分习题和评分标准

依据相关规定试卷必须按评分标准进行批改。 给分一定是宽松的&#xff0c;能给分一定给&#xff0c;如有疑问也可以向学院教务办申请查卷。 一部分学生期末成绩由于紧张或其他原因导致分数过低&#xff0c;也是非常非常遗憾的。 个人也是非常抱歉的。 开卷考试 简答题 第一…

linux之进程信号(初识信号,信号的产生)

目录 引入一、初识信号(信号预备知识)1.生活中的信号2.Linux中的信号3.信号进程得出的初步结论 二、信号的产生1.通过终端输入产生信号拓展: 硬件中断2.调用系统函数向进程发信号3.硬件异常产生信号4.软件条件产生信号拓展: 核心转储技术总结一下&#xff1a; 引入 一、初识信…

【工具类】获取日出日落时间的Java工具类

博主介绍&#xff1a;✌全网粉丝22W&#xff0c;CSDN博客专家、Java领域优质创作者&#xff0c;掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围&#xff1a;SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…

Open FPV VTX开源之betaflight配置

Open FPV VTX开源之betaflight配置 1. 源由2. 配置3. 总结4. 参考资料5. 补充 - 飞控固件版本 1. 源由 飞控嵌入式OSD - ardupilot配置使用betaflight配套OSD图片。 Choose correct font depending on Flight Controller SW. ──> /usr/share/fonts/├──> font_btfl…

Python从0到100(八十三):神经网络-使用残差网络RESNET识别手写数字

前言: 零基础学Python:Python从0到100最新最全教程。 想做这件事情很久了,这次我更新了自己所写过的所有博客,汇集成了Python从0到100,共一百节课,帮助大家一个月时间里从零基础到学习Python基础语法、Python爬虫、Web开发、 计算机视觉、机器学习、神经网络以及人工智能…

docker安装和测试redis步骤

docker安装和测试redis步骤 一、官方推荐安装方式&#xff1a; 1、执行 docker pull redis:4.0.1 命令&#xff0c;下载 redis 镜像&#xff0c;如下所示&#xff1a; 2、执行命令&#xff0c;创建并启动redis容器 docker run - -rm -d - -name redis6379 -p 6379:6379 r…