从内存巷弄到指针大道(一)

文章目录

  • 1.内存和地址
    • 1.1理解内存地址
      • 酒店大堂:内存的入口
      • 房间号:内存地址的意义
      • 酒店的楼层划分:内存的结构
      • 酒店的房间单位:计算机中的常见单位
    • 1.2如何理解编址
  • 2.指针变量和地址
    • 2.1取地址操作符(`&`)
    • 2.2 指针变量和解引用操作符(`*`)以及如何 拆解指针类型
    • 2.3使用指针的好处
    • 2.4指针变量的大小
      • 为什么指针变量的大小固定?
  • 3.指针变量类型的意义
    • 指针变量的类型
    • 指针的解引用
    • 数据类型大小的差异
      • 示例代码
    • 3.2 指针与整数的加减操作
      • 加法操作
      • 减法操作
      • 背后的原理
      • 使用场景
    • 3.3void*指针
  • 4. const修饰指针
    • 4.1`const`的使用
    • 4.2.const修饰指针的应用场景
  • 5.指针运算
    • 5.1 指针与整数相加减
      • 5.2指针之间的减法运算
      • 5.3指针的关系运算
  • 6.野指针
    • 6.1 野指针的成因
      • 未初始化指针
      • 指针指向已释放的内存
      • 指针越界
    • 6.2 野指针的危害
    • 6.3 规避野指针的策略
      • 及时初始化指针
      • 确保指针指向有效内存
      • 及时释放指针指向的内存
      • 避免指针越界
  • 7. assert断言
    • 7.1什么是断言?
      • 7.2 assert宏的用法
    • 7.3 assert的实践指南
    • 7.4 示例代码
  • 8.指针的使用和传址调用和传值调用
    • 8.1strlen 函数的模拟实现
    • 8.2传值调用和传址调用的示例:
      • 小结

在这里插入图片描述

1.内存和地址

在这里插入图片描述

1.1理解内存地址

酒店大堂:内存的入口

当你走进一家酒店时,大堂是你首先到达的地方,正如CPU访问内存时,它通过内存地址找到数据的存放位置。每个内存地址都像是房间的门牌号,告诉CPU它需要的数据住在哪个“房间”里。

房间号:内存地址的意义

在这家酒店(内存)中,每个房间(内存单元)都有一个独一无二的号码(地址)。这些号码不仅帮助客人(CPU)找到他们的房间(数据),还揭示了酒店(内存)的组织结构。与酒店的房间号码一样,内存地址是顺序排列的,这让寻找连续的数据块变得容易。

酒店的楼层划分:内存的结构

酒店楼层被划分成了不同的区域,每个区域代表了内存中的一个特定部分。这种划分有助于提高酒店运营的效率,同样,内存划分也旨在优化计算机资源的使用。

  • 前台区域(寄存器):这是最快速访问的区域,用于处理客人(数据)的即时请求。在内存中,这相当于CPU寄存器,提供了最快的数据访问速度。
  • VIP区(缓存):位于前台附近的是VIP区,访问速度快于普通房间,用于存放短期内频繁访问的贵宾客人(数据)。这对应于计算机的缓存,它存储了近期将被频繁使用的数据,以减少访问主内存的时间。
  • 客房区(主内存):酒店的主体部分,为大多数客人提供住宿服务。在计算机中,这相当于主内存,存储了当前正在使用的程序和数据。
  • 地下室(硬盘/二级存储):虽然访问速度不如楼上的区域,地下室用于存放不常用但仍需要保留的物品。这在计算机中对应于硬盘或其他形式的二级存储,用于长期存储数据。

酒店的房间单位:计算机中的常见单位

在管理这家酒店时,了解不同房间的大小和类型是必要的。类似地,在计算机中,我们也有多种单位来衡量内存和数据的大小:

  • 字节(Byte):最基本的存储单位,好比酒店中的一个储物柜,足以存放少量物品(数据)。
  • 千字节(KB,Kilobyte):约等于1000字节,相当于一个小衣橱,可以存储更多的物品。
  • 兆字节(MB,Megabyte):约等于1000千字节,像是一个小房间,用于存放更大量的物品。
  • 吉字节(GB,Gigabyte):约等于1000兆字节,等同于一间大客房,能存储大量数据。
  • 太字节(TB,Terabyte):约等于1000吉字节,好比酒店中的一整层楼,为存储巨量的数据提供空间。
    在这里插入图片描述


内存单元的编号 == 地址== 指针

1.2如何理解编址


在这里硬件与硬件之间的协同合作是通过“线”来连接的,这里是被叫做地址总线。那么,什么是地址总线呢?
简单来说,地址总线可以理解为一系列用于传递电脉冲信号的线路。在地址总线上,每一根线路都可以承载一个电脉冲信号,这个信号通常是二进制的,也就是说它可以是有电(表示为1)或者无电(表示为0)。CPU通过这些有电和无电的信号组合来指定内存中的具体地址。

例如,假设有一个4位的地址总线,那么它可以有(2^4 = 16)种不同的信号组合,从0000到1111,分别可以用来指定内存中的16个不同的位置。CPU通过在这四条线路上发送特定的有电(1)和无电(0)的组合,来告诉内存它想要访问的确切位置。每一个含义都是一个地址。
地址信息被下达给内存,在内存上就可以找到与该地址相对应的数据,将数据通过数据总线转存到CPU寄存器。

理解了变量在内存中是如何存储的。现在我们可以知道:每个变量都有一个内存地址,这个地址可以通过使用&运算符来获取。

#include <stdio.h>int main(){int var = 5;printf("变量的地址:%p\n", &var);return 0;
}

2.指针变量和地址

在这里插入图片描述

2.1取地址操作符(&)

取地址操作符&是一个一元操作符,用于获取变量在内存中的地址。当你在一个变量前使用&时,它返回该变量的内存地址。例如:

#include <stdio.h>int main()
{int var = 5;printf("%d\n", var);printf("变量的地址:%p\n", &var);return 0;
}

在这里插入图片描述
先使用的是比较小的地址
在这里插入图片描述

2.2 指针变量和解引用操作符(*)以及如何 拆解指针类型

在这里插入图片描述

指针变量是存储另一个变量地址的变量。它不同于一般的变量,指针变量指向的是位置,而不是值。声明一个指针变量时,你需要在其类型前加上*符号。例如,int* ptr;声明了一个指向整型的指针变量ptr

指针变量用于存储变量的地址,如下所示:

#include <stdio.h>int main() 
{int var = 5;int *ptr = &var;printf("指针ptr存储的地址:%p\n", ptr);printf("通过ptr访问var的值:%d\n", *ptr); // *ptr是解引用操作,得到存储在ptr地址的整型数据return 0;
}

2.3使用指针的好处

使用指针的原因可以通过一个现实生活中的类比来更好地理解:
假设你有一本非常重要的书,你想与多个朋友分享。你有两个选项:一是给每个朋友复制一本书(相当于在程序中复制数据),这样做非常耗费资源(纸张、墨水等);二是告诉朋友们这本书在你家的确切位置(相当于使用指针),让他们自己来查阅。

以下是使用指针的几个主要优点:

  1. 节省资源:与复制完整数据相比,共享数据的位置(即地址)可以显著减少内存使用。在上述类比中,复制书籍消耗的资源要远多于仅仅共享书籍的位置。

  2. 提高效率:当需要在程序的不同部分或者不同函数间共享大量数据时,使用指针可以直接访问数据,而不是花时间和资源去复制数据。就像你告诉朋友们书的位置,他们可以直接访问,而不需要等待你复制并递送一本书给他们。

  3. 允许修改原数据:通过指针,函数可以直接修改原始数据的值,而不仅仅是它的副本。这就像你允许朋友在你的书上做标记,所有查阅这本书的人都能看到这些更改,而不是每个人都在不同的副本上做标记,这些更改互不影响。

  4. 支持动态数据结构:指针是实现诸如链表、树、图等动态数据结构的关键。这些结构在运行时可以扩展和缩减,需要指针来指向和链接其各个部分。就像在一个巨大的图书馆里,书籍可能不会按顺序排列,但你可以通过一个系统(指针)来找到每本书的确切位置。

  5. 实现复杂的数据结构:在C语言中,指针是实现数组、字符串和其他复杂数据结构的基础。通过指针,可以灵活地操作这些结构中的元素,就像你可以通过书架的索引系统来快速找到任何一本书一样滴。

所以容易看出指针是程序设计中的一种强大工具,它通过提供对内存直接访问的能力,使得资源管理更高效,数据处理更灵活。理解和掌握指针,就像学会在图书馆中熟练地找到任何一本书,是提高编程技能的重要一步!!!

2.4指针变量的大小

在讨论指针变量的大小时,我们实际上是在讨论指针变量本身占用的内存空间大小。这与指针指向的数据的大小无关,而是指存储内存地址所需要的空间大小。指针变量的大小取决于计算机的架构(32位或64位)和操作系统。

为什么指针变量的大小固定?

无论指针指向的是一个整数、一个字符还是一个复杂的结构体,指针本身的大小都是固定的。这是因为指针变量只存储内存地址,而内存地址的大小是由计算机的架构决定的。

  • 32位系统中的指针:在32位系统中,地址空间是基于32位地址的,这意味着系统可以寻址(2^{32})个独立的内存地址。因此,在32位系统中,指针变量通常占用4字节(32位)的内存空间。

  • 64位系统中的指针:相比之下,64位系统可以寻址(2^{64})个独立的内存地址,这大大增加了可用的内存空间。因此,在64位系统中,指针变量的大小通常是8字节(64位)。

3.指针变量类型的意义

在这里插入图片描述

指针变量的类型

虽然指针大小和指针类型无关,指针类型定义了指针指向的数据类型。但这对于解引用操作和指针算术运算来说非常重要,因为它决定了指针操作时应该考虑的内存大小。

int* ptr; // 指向整型的指针
char* cptr; // 指向字符的指针

每种类型的指针都有其对应的内存地址大小,但指向的数据类型决定了解引用时的行为。

指针的解引用

解引用是通过指针访问其指向地址中存储的数据的操作。使用解引用操作符*来获取指针指向的值。

char*int*是C语言中两种不同类型的指针,它们的主要区别在于所指向的数据类型及通过这些指针进行操作时内存中读取或修改数据的方式。char*是指向字符数据的指针,而int*是指向整型数据的指针。这一差异影响了指针运算和解引用操作的行为。

数据类型大小的差异

在大多数平台上,char类型占用1字节,而int类型通常占用4字节(这可能根据不同的系统或编译器有所不同)。这意味着当你通过这些指针进行加减运算时,指针的移动步长也会有所不同。

示例代码

让我们通过一个例子来演示这两种指针类型的区别:

#include <stdio.h>
int main()
{int var = 0x11223344;int* ptr = &var;*ptr = 0;return 0;
}

在这里插入图片描述

在这里插入图片描述

#include <stdio.h>int main()
{int var = 0x11223344;char * ptr = &var;*ptr = 0;return 0;
}

在这里插入图片描述

容易看出int*能访问四个字节,而char解引用只能访问一个字节

3.2 指针与整数的加减操作

指针加上或减去一个整数会导致指针向前或向后移动一定数量的内存位置。这里的“一定数量”取决于指针指向的数据类型的大小。

加法操作

当我们对指针执行加法操作时,我们实际上是在移动指针。例如,如果我们有一个指向int类型的指针,每个int占用4个字节(这可能因编译器和平台而异),那么当我们对这个指针加2时,实际上是让指针向前移动了8个字节,指向了第三个整数。

#include <stdio.h>int main(){int arr[] = {10, 20, 30, 40, 50};int* ptr = arr; // 指向数组的第一个元素ptr += 2; // 移动指针到第三个元素printf("当前指针指向的值为: %d\n", *ptr); // 输出30return 0;
}

减法操作

类似地,对指针执行减法操作会使指针向后移动。使用同样的int指针例子,如果我们从指向第三个整数的指针中减去1,那么指针会移动回第二个整数的位置。

include <stdio.h>int main() 
{int arr[] = {10, 20, 30, 40, 50};int* ptr = arr + 2; // 初始时指向数组的第三个元素ptr -= 1; // 移动指针回到第二个元素printf("当前指针指向的值为: %d\n", *ptr); // 输出20return 0;
}

指针的类型就是决定向前或向后一步能走多远的(距离)
在这里插入图片描述

背后的原理

指针加减整数的操作背后的原理基于内存地址的算术运算。当我们对指针加上(或减去)一个整数时,编译器会将这个整数乘以指针指向的数据类型的大小(以字节为单位),然后将结果加到(或从)指针的当前值上。这就是为什么指针的移动会依赖于它所指向的数据类型的大小。

使用场景

指针与整数的加减操作在多种场景下非常有用,例如遍历数组、动态内存管理等。

3.3void*指针

void指针可以理解为无具体类型指针,(泛型指针)可以接收任意类型地址,但是不能进行指针的±整数和解引用的运算

在这里插入图片描述

在上面代码中,int类型的变量地址赋给char*类型的指针变量,会有如此警告
下面我们使用void*指针接收地址

容易看出void*可以接收不同类型的地址,但无法进行运算
一般是使用在函数参数的部分,用来接收不同类型数据的地址,达到泛型编程,使一个函数处理多种数据

在C语言中,const修饰符用于声明常量,而当const与指针结合使用时,产生了一些独特的语义和行为。本文将深入探讨const修饰指针的技术性,并提供详细的代码示例,帮助读者更好地理解其应用与原理。

4. const修饰指针

在这里插入图片描述

4.1const的使用

const修饰指针的语法形式为:const int *ptr;int *const ptr;
第一种形式表示指针指向的数据是常量,第二种形式表示指针本身是常量。

  • 指向常量的指针:指针指向的数据是常量,不能通过指针修改该数据。
    指向内容不可修改,指向对象可以修改
const int num = 10;
const int *ptr = &num;
//*ptr = 20; // 错误:无法修改指针所指向的数据
//ptr = &another_num//正确;可以修改指针指向
  • 常量指针:指针本身是常量,不能修改指针的指向。
int num = 10;
int *const ptr = &num;
//*ptr = 20; // 正确:可以修改指针所指向的数据
//ptr = &another_num; // 错误:无法修改指针本身的指向

4.2.const修饰指针的应用场景

  • 函数参数中的常量指针:用于传递不希望修改的数据,同时保证函数内部不会修改该数据。
void print_data(const int *ptr) 
{printf("Value: %d\n", *ptr);
}int main() 
{int num = 10;print_data(&num);return 0;
}
  • 常量指针与字符串常量:常量指针经常用于指向字符串常量,以保护字符串数据不被修改。
const char *str = "Hello, world!";
// *str = 'h'; // 错误:无法修改指向的字符串数据

在c艹中const修饰的彻底是常量

5.指针运算

在这里插入图片描述

5.1 指针与整数相加减

指针与整数相加减是指针运算中最基本的操作之一,它允许程序员在内存中进行灵活的定位和偏移。

#include <stdio.h>int main(){int arr[] = {10, 20, 30, 40, 50};int *ptr = arr; // 指向数组的第一个元素// 指针加整数,实现指针偏移ptr = ptr + 2; // ptr现在指向数组的第三个元素printf("Value: %d\n", *ptr); // 输出30// 指针减整数,实现指针偏移ptr = ptr - 1; // ptr现在指向数组的第二个元素printf("Value: %d\n", *ptr); // 输出20return 0;
}

在这个示例中,指针 ptr 指向了一个整型数组 arr 的第一个元素。通过将指针与整数相加减,可以实现对指针的偏移,从而实现对数组中不同位置的访问。
上面已经讲过了,这里只是再提一下

5.2指针之间的减法运算

指针之间的减法运算可以得到它们之间的距离(以元素个数为单位),这对于计算数组中元素的个数或者实现迭代器等功能十分有用。

#include <stdio.h>int main() 
{int arr[] = {10, 20, 30, 40, 50};int *ptr1 = &arr[0]; // 指向数组的第一个元素int *ptr2 = &arr[3]; // 指向数组的第四个元素// 指针相减,得到指针之间的距离(以元素个数为单位)int distance = ptr2 - ptr1;printf("Distance: %d\n", distance); // 输出3,即ptr2与ptr1之间相隔3个元素return 0;
}

在这个示例中,通过指针 ptr1ptr2 的减法运算,得到它们之间相隔的元素个数,即数组中的距离。

5.3指针的关系运算

指针之间还可以进行关系运算,包括相等性比较和大小比较。

#include <stdio.h>int main() {int arr[] = {10, 20, 30, 40, 50};int *ptr1 = &arr[1];int *ptr2 = &arr[3];// 指针相等性比较if (ptr1 == ptr2) {printf("Pointers are equal.\n");} else {printf("Pointers are not equal.\n");}// 指针大小比较if (ptr1 < ptr2) {printf("ptr1 is less than ptr2.\n");}else{printf("ptr1 is not less than ptr2.\n");}return 0;
}

在这个示例中,指针 ptr1ptr2 分别指向数组中的不同元素。通过关系运算符,可以判断指针之间的相等性和大小关系。

6.野指针

在这里插入图片描述

6.1 野指针的成因

未初始化指针

int *ptr;
printf("%d", *ptr); // 未初始化的指针ptr被解引用,指向未知内存地址

指针指向已释放的内存

#include <stdio.h>
#include <stdlib.h>int main() 
{int *ptr = (int *)malloc(sizeof(int)); // 分配内存空间if (ptr != NULL) {*ptr = 10; // 向分配的内存空间写入数据printf("Value: %d\n", *ptr); // 输出数据free(ptr); // 释放内存空间ptr = NULL; // 将指针置为NULL,防止成为野指针printf("Value: %d\n", *ptr); // 试图访问已经释放的内存空间}return 0;
}

在这个例子中,指针 ptr 在使用 malloc() 分配了内存空间后,被用来存储一个整数值,并通过 printf() 函数输出了该值。然后,通过 free() 函数释放了 ptr 所指向的内存空间,并将 ptr 设置为 NULL。最后,尝试再次使用 printf() 输出 ptr 所指向的值,此时 ptr 已经成为了野指针,因为它指向的内存空间已经被释放,这可能导致程序出现不可预测的行为。

指针越界

int *get_pointer() 
{int num = 10;int *ptr = &num;return ptr; // 返回了一个局部变量的指针
}int main(){int *ptr = get_pointer();printf("%d", *ptr); // ptr指向的内存超出了作用域,成为了野指针return 0;
}

6.2 野指针的危害

  • 野指针可能导致程序崩溃或产生不可预测的行为。
  • 在调试过程中,野指针可能会给程序员带来困惑和耗费大量的时间来定位问题的根源。
  • 野指针可能会导致内存泄漏或内存损坏,从而影响程序的性能和稳定性。

6.3 规避野指针的策略

及时初始化指针

int *ptr = NULL; // 显式初始化指针为空指针

确保指针指向有效内存

int *ptr = (int *)malloc(sizeof(int));
if (ptr != NULL) 
{// 分配内存成功后再进行操作
}

及时释放指针指向的内存

int *ptr = (int *)malloc(sizeof(int));
if (ptr != NULL) 
{free(ptr);ptr = NULL; // 释放内存后将指针置为空指针
}

避免指针越界

int *get_pointer() 
{int num = 10;int *ptr = &num;return ptr; // 返回局部变量的指针会导致野指针
}

7. assert断言

在这里插入图片描述

assert宏的用法、原理和实践指南

7.1什么是断言?

在C语言中,断言是一种在程序中加入的检查点,用于检查程序的假设是否成立。
如果假设不成立,则断言将导致程序终止并输出相关的错误信息,帮助程序员定位问题所在。

7.2 assert宏的用法

assert宏定义在<assert.h>头文件中,其基本语法如下:

#include <assert.h>assert(expression);

其中,expression是一个表达式,如果表达式的值为假(即0),则assert宏将终止程序的执行,并输出相应的错误信息。

7.3 assert的实践指南

  • 合理选择断言的位置:将断言放置在程序中的关键位置,如函数入口、循环体内部、关键计算或数据操作之前。

  • 明确表达断言的意图:断言的表达式应该简洁明了,能够清晰地表达程序的假设或条件。

  • 避免副作用:在断言中避免引入副作用,以免影响程序的正常运行。

  • 编译时开启断言:在开发和测试阶段,建议将断言开启,以便及时发现和解决问题。

  • 谨慎使用断言:断言应该用于检测程序的不变条件和可预期的错误情况,而不是用于处理运行时错误或非预期的情况。

7.4 示例代码

#include <stdio.h>
#include <assert.h>int main() 
{int x = 10;int y = 20;// 检查假设:x 应该小于 yassert(x < y);printf("Assertion passed: x is less than y\n");return 0;
}

在这个示例中,断言检查了表达式 x < y 是否成立,如果不成立,则程序终止并输出相应的错误信息;否则,输出“Assertion passed: x is less than y”。
如果不需要了,在#include <assert.h>加上desine NDBUG,编译器就会禁用所有assert()语句。

8.指针的使用和传址调用和传值调用

在这里插入图片描述

8.1strlen 函数的模拟实现

strlen 函数用于计算字符串的长度,它计算的是/0之前的长度,并返回字符串的长度。以下是 strlen 函数的简化模拟实现:

#include <stdio.h>// 模拟实现 strlen 函数
size_t myStrlen(const char *str) 
{const char *ptr = str;while (*ptr != '\0') {ptr++;}return ptr - str;
}int main() {char str[] = "Hello, world!";size_t len = myStrlen(str);printf("Length of '%s' is %zu\n", str, len);return 0;
}

在这个示例中,myStrlen 函数通过遍历字符串直到遇到终止符 \0 来计算字符串的长度,并返回结果。

8.2传值调用和传址调用的示例:

在这里插入图片描述
在这里插入图片描述
很容易看出x和a,y和b的地址不一样,xy是独立的空间,在swap1里面交换x和y。不会影响a和b,swap1在使用的时候是直接吧变量本身传给了函数,这就是传值调用。
形参是实参的一份临时拷贝,对形参修改不影响实参。
swap1是失败的
在这里插入图片描述
传址调用可以让函数和主调函数之间建立真正的联系,在函数内部修改主调函数的变量

小结

所以未来函数中只是需要主调函数的变量来实现计算,就可以传值,若要修改主调函数中的变量的值,就需要传址调用。
在这里插入图片描述
——end(…)

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

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

相关文章

二、typescript基础语法

一、条件语句 二、函数 1、有名函数 function add(x:number, y:number):number {return x y;}2、匿名函数 let add function (x:number, y:number):number {return x y;}函数可选参数 function buildName(firstname: string, lastname?:string) {if (lastname) {return fi…

小程序插件引用vant方式

小程序主体项目构建npm包&#xff0c;引入vant 首先要创建插件&#xff0c;不知道的去官网看下&#xff0c;直通链接 构建npm包&#xff0c;直接在小程序打开终端 npm install npm i vant/weapp -S --production记得修改 project.config.json {..."setting": {...…

模式结果和观测的对比

首先对模式的海表温度进行对比 (base) [chengxllogin02 10yearmean]$ ls sst_*.nc sst_2000.nc sst_2002.nc sst_2004.nc sst_2006.nc sst_2008.nc sst_2001.nc sst_2003.nc sst_2005.nc sst_2007.nc sst_2009.nc 首先将观测资料转化为年平均 ls sst.200* |xargs -I{} cdo -b f…

​2024年保护微服务的前10种技术

1*5rY-jEv7qlpa_swi4WMIBw.png 引言 与当前正在使用的任何其他技术或方法一样&#xff0c;微服务也有其自己的一套缺陷和问题。尽管如此&#xff0c;微服务架构的采用率不断增加&#xff0c;预计到2028年将达到1718.2亿美元。 然而&#xff0c;尽管团队使用微服务&#xff0c;但…

如何默认管理员开启CMD

许多朋友使用win10系统的时候经常会用到CMD命令&#xff0c;而且还要以管理员身份运行&#xff0c;那么如何设置默认打开cmd都是以管理员身份运行&#xff0c;设置的方法挺简单&#xff0c;大家跟着下面的步骤操作即可。 Win10怎么默认以管理员身份运行cmd&#xff1f; 1、在开…

解读 Xend Finance:向 RWA 叙事拓展,构建更具包容性的 DeFi 体系

在二十世纪后&#xff0c;非洲地区陆续爆发了主权运动&#xff0c;这也让非洲大陆逐渐摆脱“殖民地”的标签。目前&#xff0c;非洲大陆公有 54 个主权国家&#xff0c;接近 15 亿且仍在飙升的人口规模&#xff0c;其 GDP 已经与印度相当&#xff0c;且仍旧处于飞速的发展进程中…

【机器学习300问】44、P-R曲线是如何权衡精确率和召回率的?

关于精确率和召回率的基础概念我已经写了两篇文章&#xff0c;如果友友还不知道这两个评估指标是什么&#xff0c;可以先移步去看看这两篇文章&#xff1a; 【机器学习300问】25、常见的模型评估指标有哪些&#xff1f;http://t.csdnimg.cn/JtuUO 总结一下这两个概念&a…

SQL Server 文件组详解

数据文件组 SQL Server 数据库最常用的存储文件是数据文件和日志文件。 数据文件用于存储数据&#xff0c;由一个主要数据文件&#xff08;.mdf&#xff09;和若干个次要数据文件&#xff08;.ndf&#xff09;构成&#xff1b;日志文件用于存储事物日志&#xff0c;由.ldf文件…

Java全栈课程之Linux———基本属性

一、看懂文件属性 Linux系统是一种典型的多用户系统&#xff0c;不同的用户处于不同的地位&#xff0c;拥有不同的权限。为了保护系统的安全性&#xff0c;Linux系统对不同的用户访问同一文件&#xff08;包括目录文件&#xff09;的权限做了不同的规定。 在Linux中我们可以使…

2000元投影仪坚果N1 Air怎么样?对比D5X哪款更好?

投影仪市场&#xff0c;近年来作为家电数码领域的新星&#xff0c;已经引起了广泛的关注。特别是在年轻人群体中&#xff0c;投影仪成为了提升生活品质、享受家庭娱乐时光的重要工具。随着市场的繁荣&#xff0c;各种品牌和型号的投影仪如雨后春笋般涌现&#xff0c;其中&#…

Linux--进程(1)

目录 前言 1.冯诺依曼体系结构 2. 操作系统(Operator System)--第一个被加载的软件 3.进程 3.1基本概念 3.2Linux中的PCB 3.3通过系统调用创建子进程-fork初识 fork&#xff1a;创建一个子进程 为什么要创建子进程&#xff1f; fork的原理&#xff1a; 进一步了解fo…

Mora: Enabling Generalist Video Generation via A Multi-Agent Framework

Mora: Enabling Generalist Video Generation via A Multi-Agent Framework PDF: https://arxiv.org/html/2403.13248v1 1 概述 为弥补Sora不开源的缺陷&#xff0c;本文提出多代理框架Mora&#xff0c;整合先进视觉AI代理&#xff0c;复制Sora的全能视频生成能力。Mora能利用…

2024年《期刊引证报告》解读,迎来哪些新调整?

​ 【SciencePub学术】 近日&#xff0c;科睿唯安官方发布了一则关于2024年《期刊引证报告》&#xff1a;为增强透明度和包容性&#xff0c;期刊影响因子学科排名迎来新调整的文章。文章中对今年新调整过的地方做出了详细的解释。 截图来源&#xff1a;科睿唯安公众号 动态一…

#Linux(连接档概念)

&#xff08;一&#xff09;发行版&#xff1a;Ubuntu16.04.7 &#xff08;二&#xff09;记录&#xff1a; &#xff08;1&#xff09;硬链接&#xff08;inode&#xff0c;建立硬链接的文件inode号相同&#xff09; &#xff08;2&#xff09;创建硬链接:ln 文件名1 文件名…

css设置div的2个span一个在最左边,一个在最右边

界面&#xff1a; 代码&#xff1a; <html><style>.top span {display: block;position: absolute;margin: 0 20px; /* 添加边距以避免太靠近边缘 */ }.top span:nth-child(1) {left: 5px; /* 调整左侧位置 */ }.top span:nth-child(2) {right: 5px; /* 调整右侧位…

【前端性能】前端性能优化方法总结

关于前端性能指标和测量方法可以看这篇&#xff1a;【前端性能】前端性能指标和测量方法总结 文章目录 前端性能优化网络方向HTTP缓存本地储存HTTP升级DNS预解析使用CDN 渲染方向HTMLCSSJS图片Webpack优化 前端性能优化 可以从网络请求方向和页面渲染方向进行优化&#xff1a…

鸿蒙一次开发,多端部署(六)自适应布局

针对常见的开发场景&#xff0c;方舟开发框架提炼了七种自适应布局能力&#xff0c;这些布局可以独立使用&#xff0c;也可多种布局叠加使用。 下面我们依次介绍这几种自适应布局能力。 拉伸能力 拉伸能力是指容器组件尺寸发生变化时&#xff0c;增加或减小的空间全部分配给容…

鸿蒙一次开发,多端部署(十一)设置应用页面

本小节以“设置”应用页面为例&#xff0c;介绍如何使用自适应布局能力和响应式布局能力适配不同尺寸窗口。 页面设计 为充分利用屏幕尺寸优势&#xff0c;应用常常有在小屏设备上单栏显示&#xff0c;大屏设备上左右分两栏显示的设计&#xff0c;设置应用页面设计如下。 观察…

不要取和所用方法名字相同的类

package 练习; import java.util.*; public class StringBuilder {public static void main(String[] args){Scanner scan new Scanner(System.in);String r scan.nextLine();StringBuilder x new StringBuilder(r);System.out.println(x);}} 奉上错误代码&#xff08;上面&…

qt5-入门-标签页部件QTabWidget-1

参考&#xff1a; C GUI Programming with Qt 4, Second Edition 本地环境&#xff1a; win10专业版&#xff0c;64位&#xff0c;Qt5.12 目录 效果实现Qt Designer操作代码addStretch()解释 效果 首页有三个按钮和最近文件列表。 拖动窗口&#xff0c;按钮和文件列表仍然处…