C语言基础 9. 指针

C语言基础 9. 指针

文章目录

  • C语言基础 9. 指针
    • 9.1. &
    • 9.2. 指针
    • 9.3. 指针的使用
    • 9.4. 指针与数组
    • 9.5. 指针与const
    • 9.6. 指针运算
    • 9.7. 动态内存分配

9.1. &

  • 运算符&:

    • scanf(“%d”, &i);里的&

    • 获得变量的地址, 它的操作数必须是变量

      • int i;printf(“%x”, &i);
    • 地址的大小是否与int相同取决于编译器和操作系统

      • int i; printf(“%p”, &i);
      • %p: 让printf()输出地址(一个十六进制的数)
  • &不能取的地址:

    • 不能对没有地址的东西取地址
      • printf(“%p”, &(a + b));
      • printf(“%p”, &(a++));
      • printf(“%p”, &(++a)); //error: 表达式必须为左值或函数指示符
  • 试试这些&:

    • 变量的地址

      • printf(“%p\n”, &i);
    • 相邻变量的地址

      • 相邻变量: 指的是定义在相邻位置的变量, 即int i; int p; int b;, 这三个变量是相邻创建的, 也就意味着它们的地址也是相邻的

      • printf(“%p\n”, &i); //000000BE57CFFB14

      • printf(“%p\n”, &p); //000000BE57CFFB34

      • printf(“%p\n”, &b); //000000BE57CFFB54

        • i和p的地址的差值为20byte, p和b的地址的差值为20byte, 按理来说, 它们之间的差值应该是sizeof(i)=4byte, 这是为什么呢?
      • 通过上网查询以及对收集到的信息进行的反复试验, 得出了一些结论

        • 在32位操作系统上:
          • F4-E8=12, 两个相邻变量, Debug模式下, 在int变量的前后各增加了4个字节, 用于存储调试信息, a的后面4个字节, b的前面4个字节, 再加上a本身的4个字节, 刚好是12个字节. 32位上的堆栈内存分配是自上而下, 从大到小, 即F4>E8
        	int a;	//a4 4 4bint b;printf("%p\n", &a);//00D8FDF4printf("%p\n", &b);//00D8FDE8	printf("%d\n", sizeof(a));//4printf("%d\n", sizeof(b));//4printf("%d\n", sizeof(&a));//4printf("%d\n", sizeof(&b));//4
        
        • 在64位操作系统上:
          • 904-8E4=20, 在64位上面, 变量的地址内存变成了8个字节, 同时在编译器的Debug模式下, 存放调式信息的大小也变成了8个字节, a后面8个字节, b前面8个字节, 再加上a本身的4个字节, 刚好是20个字节. 64位的堆栈内存分配是从小到大8E4<904
            在这里插入图片描述
        	int a;	//a8 4 8bint b;printf("%p\n", &a);//0000006CC111F8E4printf("%p\n", &b);//0000006CC111F904	printf("%d\n", sizeof(a));//4printf("%d\n", sizeof(b));//4printf("%d\n", sizeof(&a));//8printf("%d\n", sizeof(&b));//8
        
        • 更改32位或64位, 配置管理器当中的两个选项都要改成64或者32
          在这里插入图片描述

          在这里插入图片描述
          在这里插入图片描述

        • 在64位操作系统上不使用Debug模式, 而是使用Release模式:

          • Debug模式是为了存储调试信息用的, 便于程序员调试错误, 改进代码

          • Release模式是相当于发行版本, 是让用户直接使用的, 所以里面不存放调试信息, 所以两个相邻变量之间的内存相差就等于这两个变量的类型的大小, 也就是sizeof(a)

          • 更改Debug和Release模式
            在这里插入图片描述

    • &的结果的sizeof

      • printf(“%lu\n”, sizeof(&i));
    • 数组的地址
      int arr[10];
      printf(“%p\n”, &arr);
      printf(“%p\n”, arr);
      在这里插入图片描述

    • 数组单元的地址

      • printf(“%p\n”, &arr[0]);
    • 相邻的数组单元的地址
      printf(“%p\n”, &arr[0]);//0000000FF50FF940
      printf(“%p\n”, &arr[1]);//0000000FF50FF944

      • 相差了一个sizeof(int)
      • 通过测试数组的地址得出的结论: &arr = arr = &arr[0]
  • 用于测试的代码:

#include <stdio.h>int main() {//int i = 0; //int p = 0;//int b = 1;//printf("%p\n", &i);//printf("%p\n", &p);//printf("%p\n", &b);//printf("0x%x\n", &i);//printf("%p\n", &i);//printf("%lu\n", sizeof(int));//printf("%lu\n", sizeof(&i));//printf("%lu\n", sizeof(&p));///*int a = 1;//int b = 2;//printf("%p", &(a + b));//printf("%p", &(a++));//printf("%p", &(++a));*///int arr[10];printf("%p\n", &arr);//0000000FF50FF940printf("%p\n", arr);//0000000FF50FF940printf("%p\n", &arr[0]);//0000000FF50FF940printf("%p\n", &arr[1]);//0000000FF50FF944return 0;
}

9.2. 指针

  • 经典语录:

    • 学计算机一定要有一个非常强大的心理状态, 什么呢? 计算机的所有东西都是人做出来的, 别人能想得出来的, 我也一定能想得出来. 在计算机里头没有任何的黑魔法, 所有的东西只不过是我现在不知道而已, 总有一天我会把所有的细节, 所有的内容的东西全部搞明白了.
  • scanf:

    • scanf()是一个函数, 在它当中有办法拿我们传进去的地址, 把它从标准输入里面分析出来的整数, 放到我们所指定的那个变量里面去

    • 如果能够将取得的变量的地址传递给一个函数, 能否通过这个地址在那个函数内访问这个变量?

      • scanf(“%d”, &i);
    • scanf()的原型应该是怎么样的? 我们需要一个参数能保存别的变量的地址, 如何表达能够保存地址的变量? 如果把它交给一个整数, 有时候整数和地址不见得是相同的类型, 那么什么样的类型可以接收取地址得到的地址呢?

  • 指针:

    • 保存地址的变量
      int i = 1;
      int* p = &i;//p存放了i的地址, 表示p这个指针指向了变量i
      int* p, q;//p表示指针, q表示int
      int *p, q;
  • 指针变量:

    • 普通变量的值是实际的值
    • 指针变量的值是具有实际值的变量的地址
  • 作为参数的指针:

    • void f(int* p);
    • 在被调用的时候得到了某个变量的地址
      • int i = 0;
      • f(&i);
    • 在函数里面可以通过这个指针访问外面的这个i
  • 访问那个地址上的变量*:

    • *: 是一个单目运算符, 用来访问指针的值所表示的地址上的变量
    • *: 可以做右值也可以做左值
      • int k = *p;
      • *p = k + 1;
  • 传入地址:

    • int i;
    • scanf(“%d”, i);
    • 编译没有报错, 但是执行出错了, 为什么?
      • scanf()以为你传进去的是一个地址, 但是你传进去的是一个整数, 然后它用这个整数来做事情, 所以编译不一定出错, 但是运行一定会报错, 因为scanf()把读到的整数写到了不该写的地方
#include <stdio.h>void f(int* p);
void g(int k);int main() {/*int i = 1;int* p = &i;int* p, q;int *p, q;printf("%p\n", p);*/int i = 0;printf("&i = %p\n", &i);f(&i);g(i);printf("i = %d\n", i);return 0;
}void f(int* p) {printf("*p = %d\n", *p);*p = 2;printf("*p = %d\n", *p);
}void g(int k) {printf("k = %d\n", k);
}

9.3. 指针的使用

  • 指针应用场景一:

    • 交换两个变量的值swap()函数
  • 场景二:

    • 函数返回多个值, 某些值就只能通过指针返回
      • 传入的参数实际上是需要保存带回的结果的变量
    • 找出数组中的最大最小值minmax()函数
  • 场景三:

    • 函数返回运算状态, 结果通过指针返回

    • 常用的套路是让函数返回特殊的不属于有效范围内的值来表示出错:

      • -1或0(在文件操作会看到大量的例子)
    • 但是当任何数值都是有效的可能结果时, 就得分开返回

      • 后续的语言(C++, Java)采用了异常处理机制来解决这个问题
    • 两个整数做除法divide()函数, 如果除法成功, 返回1, 否则返回0

  • 野指针(指针最常见的错误):

    • 定义了指针变量, 还没有指向任何变量, 就开始使用指针, 这样会导致程序崩溃
      • int* p;
      • *p = 1;
  • swap函数, 交换两个变量的值

#include <stdio.h>void swap(int* pa, int* pb);int main() {int a = 1;int b = 2;swap(&a, &b);printf("a = %d\n", a);printf("b = %d\n", b);return 0;
}void swap(int* pa, int* pb) {int tmp = *pa;*pa = *pb;*pb = tmp;
}
  • minmax函数, 找出数组中的最大最小值
#include <stdio.h>void minmax(int a[], int length, int* min, int* max);int main(void) {int a[] = { 1,2,3,4,5,6,7,8,9,12,13,14,16,17,21,23,55, };int min, max;int length = sizeof(a) / sizeof(a[0]);minmax(a, length, &min, &max);printf("min = %d, max = %d\n", min, max);return 0;
}void minmax(int a[], int length, int* min, int* max) {*min = *max = a[0];for (int i = 1; i < length; i++) {if (a[i] < *min) {*min = a[i];}else if (a[i] > *max) {*max = a[i];}}
}
  • 两个整数做除法divide()函数, 如果除法成功, 返回1, 否则返回0
#include <stdio.h>int divide(int a, int b, int* result);int main(void) {int a = 5;int b = 2;int c;if (divide(a, b, &c) == 1) {printf("%d / %d = %d\n", a, b, c);}return 0;
}int divide(int a, int b, int* result) {int ret = 1;if (a == 0) ret = 0;else {*result = a / b;}return ret;
}
  • 野指针
#include <stdio.h>int main(void) {int k;int* p;k = 0;*p = 1;return 0;
}

9.4. 指针与数组

  • 传入函数的数组变成了什么?

    • 函数参数表中的数组实际上是指针
      • sizeof(a) == sizeof(int*)
      • 但是可以用数组的运算符[]进行运算
  • 数组参数:

    • 以下四种参数原型是等价的:
      • int sum(int* arr, int n);
        int sum(int* , int );
        int sum(int arr[], int n);
        int sum(int [], int );
  • 数组变量是特殊的指针:

    • 数组变量本身表达地址, 所以

      • int a[10];
        int* p = a; //无需用&取地址
        但是数组的单元表达的是变量, 需要用&取地址
        &a[0], &a[1]
        a == &a[0]
    • []运算符可以对数组做, 也可以对指针做
      p[0] <==> a[0]

    • *运算符可以对指针做, 也可以对数组做
      *a = 25;

    • 数组变量是const的指针, 所以不能被赋值
      int a[] <==> int* const a =…

  • 用于测试的代码:

#include <stdio.h>void minmax(int a[], int length, int* min, int* max);int main(void) {int a[] = { 1,2,3,4,5,6,7,8,9,12,13,14,16,17,21,23,55, };int min, max;printf("main sizeof(a) = %lu\n", sizeof(a));printf("main a = %p\n", a);int length = sizeof(a) / sizeof(a[0]);minmax(a, length, &min, &max);printf("min = %d, max = %d\n", min, max);printf("a[0] = %d\n", a[0]);return 0;
}void minmax(int a[], int length, int* min, int* max) {printf("minmax sizeof(a) = %lu\n", sizeof(a));printf("minmax a = %p\n", a);a[0] = 1000;*min = *max = a[0];for (int i = 1; i < length; i++) {if (a[i] < *min) {*min = a[i];}else if (a[i] > *max) {*max = a[i];}}
}

9.5. 指针与const

  • 指针与const:

    • 指针可以是const, 它所指的那个变量也可以是const
  • 如果指针是const:

    • 表示一旦得到了某个变量的地址, 不能再指向其他变量
      • int* const q = &i;//q是const
        *q = 26;
        q++; //error
  • 如果它所指的变量是const:

    • 表示不能通过这个指针去修改那个变量(并不能使得那个变量成为const)
      • int i, j;
        const int* p = &i;
        *p = 26;//error //*p是const
        i = 26;
        p = &j;
  • 这是啥意思?

    • const int* p
      int const* p //上面两个是一样的
      int* const p

    • 判断哪个被const了的标志是const在的前面还是后面, 如果const在前面则*p是const, 如果是在后面则p是const

  • 转换:

    • 总是可以把一个非const的值转换成const的

        void f(const int* x);int a = 15;f(&a);const int b = a;f(&b);b = a + 1; //error
      
    • 当要传递的参数的类型比地址大的时候, 这是常用的手段, 这样既能用比较少的字节数传递值给参数, 又能避免函数对外面的变量的修改

  • const数组:

    • const int a[] = { 1,2,3,4,5,6 };
    • 数组变量已经是const的指针了, 这里的const表明数组的每个单元都是const int
    • 所以必须通过初始化进行赋值
  • 保护数组值:

    • 因为把数组传入函数时传递的是地址, 所以那个函数内部可以修改数组的值

    • 为了保护数组不被函数破环, 可以设置参数为const

      • int sum(const int a[], int length);
#include <stdio.h>int main() {//int i = 1;//int* const q = &i;//q是const//printf("*q = %d\n", *q);// q++//*q = 26;//printf("*q = %d\n", *q);//int i, j;//const int* p = &i;*p = 26;//error //*p是const//i = 26;//p = &j;void f(const int* x);int a = 15;f(&a);const int b = a;f(&b);//b = a + 1; //errorreturn 0;
}

9.6. 指针运算

  • 指针 + 1:

    • 是在地址值上面+sizeof(指针所指的变量的类型), 而不是直接+1

    • 表示要让指针指向下一个变量

      • int a[10];
        int* p = a;

      • *p -> a[0]
        *(p + 1) == a[1];
        通项公式: *(p + n) == a[n];

    • 如果指针不是指向一片连续分配的空间, 如数组, 则这种运算没有任何意义

  • 指针计算:

    • 给指针加减一个整数(+, +=, -, -=)
    • 递增递减(++, --)
    • 两个指针相减
      • 两个地址的差除以sizeof(指针所指变量的类型), 而不是两个地址的差
    • 不能做乘除, 没意义
  • *p++:

    • 取出p所指的那个数据来, 完事后顺便把p移到下一个位置去

    • *的优先级虽然高, 但是没有++高

    • 常用于数组类的连续空间操作

    • 在某些CPU上, 这可以直接被翻译成一条汇编指令

    • 可以实现一种新的遍历数组的方法:

      	char ac[] = { 0,1,2,3,4,5,6,7,8,9,-1 };char* p = ac;while (*p != -1) {printf("%d\n", *p++);}
      
      • -1表示的是数组结尾的标志, 并不会输出
  • 指针比较:

    • <, <=, ==, >, >=, !=都可以对指针做
    • 比较它们在内存中的地址
    • 数组中的单元的地址肯定是线性递增的
  • 0地址:

    • 当然你的内存中有0地址, 但是0地址通常是个不能随便碰的地址

    • 所以你的指针不应该具有0值

    • 因此可以用0地址来表示特殊的事情

      • 返回的指针是无效的
      • 指针没有被真正初始化(先初始化为0)
    • NULL是一个预定定义的符号, 表示0地址

      • 有的编译器不愿意你用0来表示0地址
  • 指针的类型:

    • 无论指向什么类型, 所有的指针的大小都是一样的, 因为都是地址

    • 但是指向不同类型的指针是不能直接互相赋值的

      • 这是为了避免用错指针
      • q = p;
      • warning C4133: “=”: 从“char *”到“int *”的类型不兼容
  • 指针的类型转换:

    • void* 表示不知道指向什么东西的指针
      • 计算时与char*相同(但不相通)
    • 指针也可以转换类型
      • int* p = &i;
      • void* q = (void*)p;
    • 这并没有改变p所指的变量的类型, 而是让后人用不同的眼光通过p看它所指的变量
      • 我不再当你是int啦, 我认为你就是个void
  • 用指针来做什么:

    • 需要传入较大的数据时用作参数
    • 传入数组后对数组做操作
    • 函数返回不止一个结果
      • 需要用函数来修改不止一个变量
    • 动态申请的内存…
//#include <stdio.h>
//
//int main() {
//	char ac[] = { 0,1,2,3,4,5,6,7,8,9, };
//	char* p = ac;
//	printf("p = %p\n", p);//p = 00000054CA5BFBF4
//	printf("p + 1 = %p\n", p + 1);//p + 1 = 00000054CA5BFBF5
//	printf("*(p + 1) = %d\n", *(p + 1));
//	printf("ac[1] = %d\n", ac[1]);
//
//	char* p1 = &ac[5];
//	printf("p1 - p = %p\n", p1 - p);
//
//	int ai[] = { 0,1,2,3,4,5,6,7,8,9, };
//	int* q = ai;
//	printf("q = %p\n", q);//q = 000000EDD69DF5B4
//	printf("q + 1 = %p\n", q + 1);//q + 1 = 000000EDD69DF5B8
//	printf("*(q + 1) = %d\n", *(q + 1));
//	printf("ai[1] = %d\n", ai[1]);
//	/*printf("q - 1 = %p\n", q - 1);*/
//	//q += 1;
//	printf("q = %p\n", q);
//	//printf("++q = %p\n", ++q);
//
//	
//	
//	int* q1 = &ai[6];
//	printf("q1 = %p\n", q1);
//	printf("q1 - q = %p\n", q1 - q);
//
//
//	
//	printf("*q++ = %d\n", *q++);
//	printf("*q = %d\n", *q);
//	return 0;
//}#include <stdio.h>int main(void) {/*char ac[] = { 0,1,2,3,4,5,6,7,8,9,-1 };char* p = ac;while (*p != -1) {printf("%d\n", *p++);}int i[] = {1,2,3,4,};int* q = i;q = p;*/int i;int* p = &i;void* q = (void*)p;return 0;
}

9.7. 动态内存分配

  • 输入数据:

    • 如果输入数据时, 县高树你个数, 然后再输入, 要记录每个数据

    • C99可以用变量做数组定义的大小, C99之前呢?

      • 必须使用动态内存分配

      • int* a = (int*)malloc(n * sizeof(int));//借过来

      • free(a);//还回去

  • malloc:

    • #include <stdlib.h>

    • void* malloc(size_t size);

    • 向malloc申请的空间的大小是以字节为单位的

    • 返回的结果时void*, 需要类型转换为自己需要的类型

      • (int*)malloc(n * sizeof(int))
  • 没空间了?

    • 如果申请失败则返回0, 或者叫做NULL
    • 你的系统能给你多大的空间?
      • 分配了35600MB的空间
  • free():

    • 把申请得来的空间还给系统
    • 申请过的空间, 最终都应该还回去
      • 混出来的, 迟早是要还的
  • 常见问题:

    • 申请了没free->长时间运行内存逐渐下降
      • 新手: 忘了
      • 老手: 找不到合适的free的时机
    • free过了再free
    • 地址变过了, 直接去free
  • 经典

    • 纸上得来终觉浅, 绝知此事要躬行
#include <stdio.h>
#include <stdlib.h>int main() {//int n;scanf("%d", &n);//int arr[10];///*for (int i = 0; i < n; i++) {//	arr[i] = i;//	printf("%d ", arr[i]);//}*///int number;//int* a;//int i;//printf("请输入数量: ");//scanf("%d", &number);//a = (int*)malloc(number * sizeof(int));//借过来//for (i = 0; i < number; i++) {//	scanf("%d", &a[i]);//}//for (i = 0; i < number; i++) {//	printf("%d ", a[i]);//}//free(a);//还回去//系统能给你多大的空间void* p;int count = 0;while (p = malloc(100 * 1024 * 1024)) {count++;}printf("分配了%d00MB的空间\n", count);return 0;
}

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

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

相关文章

【SpringBoot Web开发之静态资源访问】笔记

详细内容见官方文档&#xff1a;Static Content SpringBoot Web开发之静态资源访问 1.准备工作&#xff1a;创建WebDemo2.静态资源目录2.1官网原文2.2静态资源目录第一步&#xff1a;依照上面2.1官网原文中创建如下目录第二步&#xff1a;复制粘贴图片到静态资源目录中第三步…

MySQL:JOIN 多表查询

多表查询 在关系型数据库中&#xff0c;表与表之间是有联系的&#xff0c;它们通过 外键 联系在一起&#xff0c;所以在实际应用中&#xff0c;经常使用多表查询。多表查询就是同时查询两个或两个以上的表。 MySQL多表查询是数据库操作中非常重要的一部分&#xff0c;它允许你…

【深入理解SpringCloud微服务】浅析微服务注册中心Eureka与nacos,手写实现一个微服务注册中心

【深入理解SpringCloud微服务】浅析微服务注册中心Eureka与nacos&#xff0c;手写实现一个微服务注册中心 注册中心手写实现一个注册中心服务端设计客户端设计 注册中心 注册中心是微服务体系里面非常重要的一个核心组件&#xff0c;它最重要的作用就是实现服务注册与发现。 …

【MyBatisPlus】快速掌握MP插件使用方法

一、MyBatis-Plus简介 1.1 简介 1.2 特性 无侵入&#xff1a;只做增强不做改变&#xff0c;引入它不会对现有工程产生影响&#xff0c;如丝般顺滑损耗小&#xff1a;启动即会自动注入基本 CURD&#xff0c;性能基本无损耗&#xff0c;直接面向对象操作强大的 CRUD 操作&#x…

【ACM独立出版|EI检索稳定】2024年智能感知与模式识别国际学术会议(ISPC 2024,9月6日-8)

2024年智能感知与模式识别国际学术会议 (ISPC 2024)将于2024年9月6日-8日于中国青岛召开。 会议将围绕智能感知与模式识别等领域中的最新研究成果&#xff0c;为来自国内外高等院校、科学研究所、企事业单位的专家、教授、学者、工程师等提供一个分享专业经验&#xff0c;扩大…

初谈Linux信号-=-信号的产生

文章目录 概述从生活角度理解信号Linux中信号信号常见的处理方式理解信号的发送与保存 信号的产生core、term区别 概述 从生活角度理解信号 你在网上买了很多件商品&#xff0c;再等待不同商品快递的到来。但即便快递没有到来&#xff0c;你也知道快递来临时&#xff0c; 你该…

机械臂泡水维修|机器人雨后进水维修措施

如果机器人不慎被水淹&#xff0c;别慌&#xff01;我们为你准备了一份紧急的机械臂泡水维修抢修指南&#xff0c;帮助你解决这个问题。 【机器人浸水被淹后紧急维修抢修&#xff5c;如何处理&#xff1f;】 机械臂被淹进水后维修处理方式 1. 机械手淹水后断电断网 首先&am…

spring整合mybatis,junit纯注解开发(包括连接druid报错的所有解决方法)

目录 Spring整合mybatis开发步骤 第一步&#xff1a;创建我们的数据表 第二步&#xff1a;编写对应的实体类 第三步&#xff1a;在pom.xml中导入我们所需要的坐标 spring所依赖的坐标 mybatis所依赖的坐标 druid数据源坐标 数据库驱动依赖 第四步&#xff1a;编写SpringC…

linux在ssh的时候询问,yes or no 如何关闭

解决&#xff1a; 在~/.ssh/config文件中添加如下配置项&#xff1a; Host *StrictHostKeyChecking no

数据可视化配色新工具,颜色盘多达2500+类

好看的配色,不仅能让图表突出主要信息,更能吸引读者,之前分享过很多配色工具,例如, 👉可视化配色工具:颜色盘多达3000+类,数万种颜色! 本次再分享一个配色工具pypalettes,颜色盘多达2500+类。 安装pypalettes pip install pypalettes pypalettes使用 第1步,挑选…

【LeetCode】分隔链表

目录 一、题目二、解法完整代码 一、题目 给你一个链表的头节点 head 和一个特定值 x &#xff0c;请你对链表进行分隔&#xff0c;使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。 你应当 保留 两个分区中每个节点的初始相对位置。 示例 1&#xff1a; 输入&a…

JVM中的GC流程与对象晋升机制

JVM中的GC流程与对象晋升机制 1、JVM堆内存结构2、Minor GC流程3、Full GC流程4、总结 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 在Java虚拟机&#xff08;JVM&#xff09;中&#xff0c;垃圾回收&#xff08;GC&#xff09;是自动管…

VTK源码分析:Type System

作为一款开源跨平台的数据可视化代码库&#xff0c;VTK以其清晰的流水线工作方式、丰富的后处理算法、异种渲染/交互方式&#xff0c;而被众多CAx软件选作后处理实施方案。而异种渲染/交互方式的实现&#xff0c;主要是倚重于VTK的类型系统&#xff0c;因此&#xff0c;有必要对…

最新 Docker 下载镜像超时解决方案:Docker proxy

现在Docker换源也下载失败太常见了&#xff0c;至于原因&#xff0c;大家懂得都懂。本文提供一种简洁的方案&#xff0c; 利用 Docker 的http-proxy&#xff0c;代理至本机的 proxy。 文章目录 前言Docker proxy 前言 这里默认你会安装 clash&#xff0c;然后有配置和数据库。…

排序算法

排序算法 内部排序&#xff1a;指将需要处理的所有数据都加载到内部存储器中进行排序 外部排序&#xff1a;数据量过大&#xff0c;无法全部加载到内存中&#xff0c;需要借助外部存储进行排序 算法的时间复杂度 一个算法花费的时间与算法中语句的执行次数成正比&#xff0c;…

Unity XR Interaction Toolkit(VR、AR交互工具包)记录安装到开发的流程,以及遇到的常见问题(一)!

提示&#xff1a;文章有错误的地方&#xff0c;还望诸位大神不吝指教&#xff01; 文章目录 前言一、XR Interaction Toolkit是什么&#xff1f;二、跨平台交互三、 AR 功能四、XR Interaction Toolkit的特点五、XR Interaction Toolkit 示例总结 前言 随着VR行业的发展&#…

一文搞懂 Java 基础:新手入门必备

目录 &#x1f4dd; Java基础Java起源第一个Java程序基础语法Java标识符Java变量Java注释Java数据类型Java运算符Java流程控制语句 &#x1f4dd; Java基础 Java起源 Java programming language具有大部分编程语言所共有的一些特征&#xff0c;被特意设计用于互联网的分布式环…

《算法笔记》总结No.10——链表

从第10期破例插叙一期单链表的实现&#xff0c;这个东东相当重要&#xff01;考研的同学也可以看&#xff1a;相较于王道考研的伪码不太相同&#xff0c;专注于可以运行。如果是笔试中的伪码&#xff0c;意思正确即可~ 注&#xff1a;博主之前写过一个版本的顺序表和单链表的C实…

Jolt路线图

1. 引言 a16z crypto团队2024年7月更新了其Jolt路线图&#xff1a; 主要分为3大维度&#xff1a; 1&#xff09;链上验证维度&#xff1a; 1.1&#xff09;Zeromorph&#xff1a;见Aztec Labs团队2023年论文 Zeromorph: Zero-Knowledge Multilinear-Evaluation Proofs from…

视觉巡线小车——STM32+OpenMV

系列文章目录 第一章&#xff1a;视觉巡线小车——STM32OpenMV&#xff08;一&#xff09; 第二章&#xff1a;视觉巡线小车——STM32OpenMV&#xff08;二&#xff09; 第三章&#xff1a;视觉巡线小车——STM32OpenMV&#xff08;三&#xff09; 第四章&#xff1a;视觉巡…