c6011取消对null指针的引用_C/C++学习笔记——C提高:指针强化

5433b11e663d40143e6c62cb0823d151.png

指针是一种数据类型

指针变量

指针是一种数据类型,占用内存空间,用来保存内存地址。

void test01(){    int* p1 = 0x1234;  int*** p2 = 0x1111;  printf("p1 size:%d\n",sizeof(p1));  printf("p2 size:%d\n",sizeof(p2));  //指针是变量,指针本身也占内存空间,指针也可以被赋值  int a = 10;  p1 = &a;  printf("p1 address:%p\n", &p1);  printf("p1 address:%p\n", p1);  printf("a address:%p\n", &a);}

野指针和空指针

空指针

标准定义了NULL指针,它作为一个特殊的指针变量,表示不指向任何东西。要使一个指针为NULL,可以给它赋值一个零值。为了测试一个指针百年来那个是否为NULL,你可以将它与零值进行比较。

对指针解引用操作可以获得它所指向的值。但从定义上看,NULL指针并未执行任何东西,因为对一个NULL指针因引用是一个非法的操作,在解引用之前,必须确保它不是一个NULL指针。

如果对一个NULL指针间接访问会发生什么呢?结果因编译器而异。

不允许向NULL和非法地址拷贝内存:

void test(){  char *p = NULL;  //给p指向的内存区域拷贝内容  strcpy(p, "1111"); //err  char *q = 0x1122;  //给q指向的内存区域拷贝内容  strcpy(q, "2222"); //err    }

野指针

在使用指针时,要避免野指针的出现:

野指针指向一个已删除的对象或未申请访问受限内存区域的指针。与空指针不同,野指针无法通过简单地判断是否为 NULL避免,而只能通过养成良好的编程习惯来尽力减少。对野指针进行操作很容易造成程序错误。

什么情况下会导致野指针?

  • 指针变量未初始化

    任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的,它会乱指一气。所以,指针变量在创建的同时应当被初始化,要么将指针设置为NULL,要么让它指向合法的内存。

  • 指针释放后未置空

    有时指针在free或delete后未赋值 NULL,便会使人以为是合法的。别看free和delete的名字(尤其是delete),它们只是把指针所指的内存给释放掉,但并没有把指针本身干掉。此时指针指向的就是“垃圾”内存。释放后的指针应立即将指针置为NULL,防止产生“野指针”。

  • 指针操作超越变量作用域

    不要返回指向栈内存的指针或引用,因为栈内存在函数结束时会被释放。

void test(){  int* p = 0x001; //未初始化  printf("%p\n",p);  *p = 100;}

操作野指针是非常危险的操作,应该规避野指针的出现:

  • 初始化时置 NULL

    指针变量一定要初始化为NULL,因为任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的。

  • 释放时置 NULL

    当指针p指向的内存空间释放时,没有设置指针p的值为NULL。delete和free只是把内存空间释放了,但是并没有将指针p的值赋为NULL。通常判断一个指针是否合法,都是使用if语句测试该指针是否为NULL。

间接访问操作符

通过一个指针访问它所指向的地址的过程叫做间接访问,或者叫解引用指针,这个用于执行间接访问的操作符是*。

注意:对一个int类型指针解引用会产生一个整型值,类似地,对一个float指针解引用会产生了一个float类型的值。

int arr[5];  int *p = * (&arr);int arr1[5][3] arr1 = int(*)[3]&arr1
  • 在指针声明时,* 号表示所声明的变量为指针

  • 在指针使用时,* 号表示操作指针所指向的内存空间
    1)* 相当通过地址(指针变量的值)找到指针指向的内存,再操作内存
    2)* 放在等号的左边赋值(给内存赋值,写内存)
    3)* 放在等号的右边取值(从内存中取值,读内存)

//解引用void test01(){  //定义指针  int* p = NULL;  //指针指向谁,就把谁的地址赋给指针  int a = 10;  p = &a;  *p = 20;//*在左边当左值,必须确保内存可写  //*号放右面,从内存中读值  int b = *p;  //必须确保内存可写  char* str = "hello world!";  *str = 'm';  printf("a:%d\n", a);  printf("*p:%d\n", *p);  printf("b:%d\n", b);}

指针的步长

指针是一种数据类型,是指它指向的内存空间的数据类型。指针所指向的内存空间决定了指针的步长。指针的步长指的是,当指针+1时候,移动多少字节单位。

思考如下问题:

int a = 0xaabbccdd;unsigned int *p1 = &a;unsigned char *p2 = &a;//为什么*p1打印出来正确结果?printf("%x\n", *p1);//为什么*p2没有打印出来正确结果?printf("%x\n", *p2);//为什么p1指针+1加了4字节?printf("p1  =%d\n", p1);printf("p1+1=%d\n", p1 + 1);//为什么p2指针+1加了1字节?printf("p2  =%d\n", p2);printf("p2+1=%d\n", p2 + 1);

指针的意义_间接赋值

间接赋值的三大条件

通过指针间接赋值成立的三大条件:
1)2个变量(一个普通变量一个指针变量、或者一个实参一个形参)
2)建立关系
3)通过 * 操作指针指向的内存

void test(){  int a = 100;  //两个变量  int *p = NULL;  //建立关系  //指针指向谁,就把谁的地址赋值给指针  p = &a;  //通过*操作内存  *p = 22;}

如何定义合适的指针变量

void test(){  int b;    int *q = &b; //0级指针  int **t = &q;  int ***m = &t;}

间接赋值:从0级指针到1级指针

int func1(){ return 10; }void func2(int a){  a = 100;}//指针的意义_间接赋值void test02(){  int a = 0;  a = func1();  printf("a = %d\n", a);  //为什么没有修改?  func2(a);  printf("a = %d\n", a);}//指针的间接赋值void func3(int* a){  *a = 100;}void test03(){  int a = 0;  a = func1();  printf("a = %d\n", a);  //修改  func3(&a);  printf("a = %d\n", a);}

间接赋值:从1级指针到2级指针

void AllocateSpace(char** p){  *p = (char*)malloc(100);  strcpy(*p, "hello world!");}void FreeSpace(char** p){  if (p == NULL){    return;  }  if (*p != NULL){    free(*p);    *p = NULL;  }}void test(){    char* p = NULL;  AllocateSpace(&p);  printf("%s\n",p);  FreeSpace(&p);  if (p == NULL){    printf("p内存释放!\n");  }}

间接赋值的推论

  • 用1级指针形参,去间接修改了0级指针(实参)的值。

  • 用2级指针形参,去间接修改了1级指针(实参)的值。

  • 用3级指针形参,去间接修改了2级指针(实参)的值。

  • 用n级指针形参,去间接修改了n-1级指针(实参)的值。

指针做函数参数

指针做函数参数,具备输入和输出特性:

  • 输入:主调函数分配内存

  • 输出:被调用函数分配内存

输入特性

void fun(char *p /* in */){  //给p指向的内存区域拷贝内容  strcpy(p, "abcddsgsd");}void test(void){  //输入,主调函数分配内存  char buf[100] = { 0 };  fun(buf);  printf("buf  = %s\n", buf);}

输出特性

void fun(char **p /* out */, int *len){  char *tmp = (char *)malloc(100);  if (tmp == NULL)  {    return;  }  strcpy(tmp, "adlsgjldsk");  //间接赋值  *p = tmp;  *len = strlen(tmp);}void test(void){  //输出,被调用函数分配内存,地址传递  char *p = NULL;  int len = 0;  fun(&p, &len);  if (p != NULL)  {    printf("p = %s, len = %d\n", p, len);  }

字符串指针强化

字符串指针做函数参数

字符串基本操作

//字符串基本操作//字符串是以0或者'\0'结尾的字符数组,(数字0和字符'\0'等价)void test01(){  //字符数组只能初始化5个字符,当输出的时候,从开始位置直到找到0结束  char str1[] = { 'h', 'e', 'l', 'l', 'o' };  printf("%s\n",str1);  //字符数组部分初始化,剩余填0  char str2[100] = { 'h', 'e', 'l', 'l', 'o' };  printf("%s\n", str2);  //如果以字符串初始化,那么编译器默认会在字符串尾部添加'\0'  char str3[] = "hello";  printf("%s\n",str3);  printf("sizeof str:%d\n",sizeof(str3));  printf("strlen str:%d\n",strlen(str3));  //sizeof计算数组大小,数组包含'\0'字符  //strlen计算字符串的长度,到'\0'结束  //那么如果我这么写,结果是多少呢?  char str4[100] = "hello";  printf("sizeof str:%d\n", sizeof(str4));  printf("strlen str:%d\n", strlen(str4));  //请问下面输入结果是多少?sizeof结果是多少?strlen结果是多少?  char str5[] = "hello\0world";   printf("%s\n",str5);  printf("sizeof str5:%d\n",sizeof(str5));  printf("strlen str5:%d\n",strlen(str5));  //再请问下面输入结果是多少?sizeof结果是多少?strlen结果是多少?  char str6[] = "hello\012world";  printf("%s\n", str6);  printf("sizeof str6:%d\n", sizeof(str6));  printf("strlen str6:%d\n", strlen(str6));}

八进制和十六进制转义字符:

在C中有两种特殊的字符,八进制转义字符和十六进制转义字符,八进制字符的一般形式是’\ddd’,d是0-7的数字。十六进制字符的一般形式是’\xhh’,h是0-9或A-F内的一个。八进制字符和十六进制字符表示的是字符的ASCII码对应的数值。

比如 :

  • ‘\063’表示的是字符’3’,因为’3’的ASCII码是30(十六进制),48(十进制),63(八进制)。

  • ‘\x41’表示的是字符’A’,因为’A’的ASCII码是41(十六进制),65(十进制),101(八进制)。

字符串拷贝功能实现

//拷贝方法1void copy_string01(char* dest, char* source ){  for (int i = 0; source[i] != '\0';i++){    dest[i] = source[i];  }}//拷贝方法2void copy_string02(char* dest, char* source){  while (*source != '\0' /* *source != 0 */){    *dest = *source;    source++;    dest++;  }}//拷贝方法3void copy_string03(char* dest, char* source){  //判断*dest是否为0,0则退出循环  while (*dest++ = *source++){}}//拷贝方法4//1)应该判断下传入的参数是否为NULL//2)最好不要直接使用形参int copy_string04(char* dest, char* source){  if (dest == NULL){    return -1;  }  if (source == NULL){    return -2;  }  char* src = source;  char* tar = dest;  while (*tar++ = *src++){}  return 0;}

字符串反转模型

d842d29df902c5c0c3ae5583c2d255eb.png

void reverse_string(char* str){  if (str == NULL){    return;  }  int begin = 0;  int end = strlen(str) - 1;    while (begin < end){        //交换两个字符元素    char temp = str[begin];    str[begin] = str[end];    str[end] = temp;    begin++;    end--;  }}void test(){  char str[] = "abcdefghijklmn";  printf("str:%s\n", str);  reverse_string(str);  printf("str:%s\n", str);}

字符串的格式化

sprintf

#include int sprintf(char *str, const char *format, ...);功能:     根据参数format字符串来转换并格式化数据,然后将结果输出到str指定的空间中,直到    出现字符串结束符 '\0'  为止。参数:  str:字符串首地址  format:字符串格式,用法和printf()一样返回值:  成功:实际格式化的字符个数  失败: - 1
void test(){    //1. 格式化字符串  char buf[1024] = { 0 };  sprintf(buf, "你好,%s,欢迎加入我们!", "John");  printf("buf:%s\n",buf);  memset(buf, 0, 1024);  sprintf(buf, "我今年%d岁了!", 20);  printf("buf:%s\n", buf);  //2. 拼接字符串  memset(buf, 0, 1024);  char str1[] = "hello";  char str2[] = "world";  int len = sprintf(buf,"%s %s",str1,str2);  printf("buf:%s len:%d\n", buf,len);  //3. 数字转字符串  memset(buf, 0, 1024);  int num = 100;  sprintf(buf, "%d", num);  printf("buf:%s\n", buf);  //设置宽度 右对齐  memset(buf, 0, 1024);  sprintf(buf, "%8d", num);  printf("buf:%s\n", buf);  //设置宽度 左对齐  memset(buf, 0, 1024);  sprintf(buf, "%-8d", num);  printf("buf:%s\n", buf);  //转成16进制字符串 小写  memset(buf, 0, 1024);  sprintf(buf, "0x%x", num);  printf("buf:%s\n", buf);  //转成8进制字符串  memset(buf, 0, 1024);  sprintf(buf, "0%o", num);  printf("buf:%s\n", buf);}

sscanf

#include int sscanf(const char *str, const char *format, ...);功能:    从str指定的字符串读取数据,并根据参数format字符串来转换并格式化数据。参数:  str:指定的字符串首地址  format:字符串格式,用法和scanf()一样返回值:  成功:实际读取的字符个数  失败: - 1

e6c1e497c4229aa5eef9eff6a3924b36.png

//1. 跳过数据void test01(){  char buf[1024] = { 0 };  //跳过前面的数字  //匹配第一个字符是否是数字,如果是,则跳过  //如果不是则停止匹配  sscanf("123456aaaa", "%*d%s", buf);   printf("buf:%s\n",buf);}//2. 读取指定宽度数据void test02(){  char buf[1024] = { 0 };  //跳过前面的数字  sscanf("123456aaaa", "%7s", buf);  printf("buf:%s\n", buf);}//3. 匹配a-z中任意字符void test03(){  char buf[1024] = { 0 };  //跳过前面的数字  //先匹配第一个字符,判断字符是否是a-z中的字符,如果是匹配  //如果不是停止匹配  sscanf("abcdefg123456", "%[a-z]", buf);  printf("buf:%s\n", buf);}//4. 匹配aBc中的任何一个void test04(){  char buf[1024] = { 0 };  //跳过前面的数字  //先匹配第一个字符是否是aBc中的一个,如果是,则匹配,如果不是则停止匹配  sscanf("abcdefg123456", "%[aBc]", buf);  printf("buf:%s\n", buf);}//5. 匹配非a的任意字符void test05(){  char buf[1024] = { 0 };  //跳过前面的数字  //先匹配第一个字符是否是aBc中的一个,如果是,则匹配,如果不是则停止匹配  sscanf("bcdefag123456", "%[^a]", buf);  printf("buf:%s\n", buf);}//6. 匹配非a-z中的任意字符void test06(){  char buf[1024] = { 0 };  //跳过前面的数字  //先匹配第一个字符是否是aBc中的一个,如果是,则匹配,如果不是则停止匹配  sscanf("123456ABCDbcdefag", "%[^a-z]", buf);  printf("buf:%s\n", buf);}

一级指针易错点

越界

void test(){  char buf[3] = "abc";  printf("buf:%s\n",buf);}

指针叠加会不断改变指针指向

void test(){  char *p = (char *)malloc(50);  char buf[] = "abcdef";  int n = strlen(buf);  int i = 0;  for (i = 0; i < n; i++)  {    *p = buf[i];    p++; //修改原指针指向  }  free(p);}

返回局部变量地址

char *get_str(){  char str[] = "abcdedsgads"; //栈区,  printf("[get_str]str = %s\n", str);  return str;}

同一块内存释放多次

void test(){    char *p = NULL;  p = (char *)malloc(50);  strcpy(p, "abcdef");  if (p != NULL)  {    //free()函数的功能只是告诉系统 p 指向的内存可以回收了    // 就是说,p 指向的内存使用权交还给系统    //但是,p的值还是原来的值(野指针),p还是指向原来的内存    free(p);  }  if (p != NULL)  {    free(p);  }}

const使用

//const修饰变量void test01(){  //1. const基本概念  const int i = 0;  //i = 100; //错误,只读变量初始化之后不能修改  //2. 定义const变量最好初始化  const int j;  //j = 100; //错误,不能再次赋值  //3. c语言的const是一个只读变量,并不是一个常量,可通过指针间接修改  const int k = 10;  //k = 100; //错误,不可直接修改,我们可通过指针间接修改  printf("k:%d\n", k);  int* p = &k;  *p = 100;  printf("k:%d\n", k);}//const 修饰指针void test02(){  int a = 10;  int b = 20;  //const放在*号左侧 修饰p_a指针指向的内存空间不能修改,但可修改指针的指向  const int* p_a = &a;  //*p_a = 100; //不可修改指针指向的内存空间  p_a = &b; //可修改指针的指向  //const放在*号的右侧, 修饰指针的指向不能修改,但是可修改指针指向的内存空间  int* const p_b = &a;  //p_b = &b; //不可修改指针的指向  *p_b = 100; //可修改指针指向的内存空间  //指针的指向和指针指向的内存空间都不能修改  const int* const p_c = &a;}//const指针用法struct Person{  char name[64];  int id;  int age;  int score;};//每次都对对象进行拷贝,效率低,应该用指针void printPersonByValue(struct Person person){  printf("Name:%s\n", person.name);  printf("Name:%d\n", person.id);  printf("Name:%d\n", person.age);  printf("Name:%d\n", person.score);}//但是用指针会有副作用,可能会不小心修改原数据void printPersonByPointer(const struct Person *person){  printf("Name:%s\n", person->name);  printf("Name:%d\n", person->id);  printf("Name:%d\n", person->age);  printf("Name:%d\n", person->score);}void test03(){  struct Person p = { "Obama", 1101, 23, 87 };  //printPersonByValue(p);  printPersonByPointer(&p);}

原文:https://blog.csdn.net/tichimi3375/article/details/104722295

END

如果您觉得本篇文章对您有帮助请转发给更多的人

顺手点一下“在看”也是对小编最大的支持

36d4d3c8ad0e9365f947505351f9d3b1.png

5e6ebf51df1301c8bca54270a41253ce.gif

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

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

相关文章

现在的人工智能只是“窄AI”?

来源丨The Next Web编辑丨科技行者1956年&#xff0c;由数学系年轻的助理教授John McCarthy领导的科学家小组齐聚新罕布什尔州的达特茅斯学院&#xff0c;计划进行一个为期六周且雄心勃勃的项目&#xff1a;创建一种能够“使用语言、形式抽象与概念&#xff0c;帮助人类解决各类…

需要单机还是集群部署_单机、集群和分布式(微服务结构)的区别

一、单机单机就是所有的业务全部写在一个项目中&#xff0c;部署服务到一台服务器上&#xff0c;所有的请求业务都由这台服务器处理。显然&#xff0c;当业务增长到一定程度的时候&#xff0c;服务器的硬件会无法满足业务需求。自然而然地想到一个程序不行就部署多个喽&#xf…

查询 oracle_ORACLE数据库查询语句

Oracle数据库————SQL基本查询一、涉及内容1.掌握SELECT 语句的基本语法。2.掌握常用函数的使用。二、具体操作(一)使用Scott方案下的emp表和dept表&#xff0c;完成以下操作&#xff1a;1.查询部门编号是20的员工信息。2.查询工作为CLERK的员工号、员工名和部门号&#xff…

2020年中国新基建产业报告(收藏)

来源&#xff1a;董秘君未来智能实验室的主要工作包括&#xff1a;建立AI智能系统智商评测体系&#xff0c;开展世界人工智能智商评测&#xff1b;开展互联网&#xff08;城市&#xff09;云脑研究计划&#xff0c;构建互联网&#xff08;城市&#xff09;云脑技术和企业图谱&a…

从云到端,谷歌的AI芯片2.0

来源&#xff1a;脑极体 得芯片者得天下。我们可以把这句话再延伸一下说&#xff0c;得AI芯片者得未来的天下。对于智能终端厂商来说&#xff0c;能够自研SoC芯片似乎才是顶级实力的象征。众所周知&#xff0c;盘踞全球智能手机前三甲的三星、华为、苹果&#xff0c;无一例外都…

Real-Time Volumetric Cloudscapes

实时体积云景 GPU Pro 7 实时体积云景的翻译 4.1 概览 游戏中的实时体积云通常为了提高渲染效率而降低质量。最成功的方法仅限于低空蓬松半透明的层状云。我们提出了一种体积解决方案&#xff0c;可以使用不断变化并且逼真的结果填充天空&#xff0c;来描绘高海拔卷云和所有…

语言条件语序心得_考研分享 | 王远新语言学教程要点总结(第五章)

点击上方蓝字&#xff0c;关注我吧作者|雨 轩编辑|武思文上次小编分享了王远新老师《语言学教程》的第四章&#xff1a;考研分享 | 王远新《语言学教程》要点总结(第四章)&#xff0c;今天小编为大家带来的是第五章的要点分享&#xff0c;希望可以帮到考研的你。第五章 语法关…

世界顶尖精密仪器技术都掌握在哪些国家?

来源&#xff1a;仪商网科技乃第一生产力&#xff0c;而技术经过时间的沉淀&#xff0c;岁月的积累&#xff0c;现实的实践&#xff0c;具备了引领时代的力量后&#xff0c;这样技术就被称为全世界最顶尖的技术。而精密仪器又是开展前沿科学研究、推动技术发展必不可少的科研工…

@modelattribute注解用postman测试怎么传参_谁要是再敢用Map传参,我过去就是一JIO...

还记得上次我写过一篇关于实际项目代码分层和规划的文章《看完这篇&#xff0c;别人的开源项目结构应该能看懂了》&#xff0c; 在文尾处提到过一些注意事项&#xff0c;其中第一条就是&#xff1a;Contorller层参数传递建议不要使用HashMap&#xff0c;推荐使用数据模型定义私…

「反向传播非你原创」,Jürgen发文直指Hinton不应获2019本田奖

来源&#xff1a;机器之心LSTM 之父 Jrgen Schmidhuber 再次掀起争论&#xff0c;这回他指向了深度学习之父、图灵奖得主 Geoffrey Hinton。不过&#xff0c;这次他站出来质疑的是 Hinton 的最新奖项——本田奖。创立于 1980 年的本田奖旨在表彰「为引领生态技术领域的下一代新…

操作文件 -------JavaScrip

本文摘要&#xff1a;http://www.liaoxuefeng.com/ 在HTML表单中&#xff0c;可以上传文件的唯一控件就是<input type"file">。 注意&#xff1a;当一个表单包含<input type"file">时&#xff0c;表单的enctype必须指定为multipart/form-data&…

半导体未来浪潮(深度好文)

本文资料来源于自德勤报告《半导体&#xff1a;未来浪潮》01新格局&#xff1a;全球半导体行业不断演化在过去几年&#xff0c;全球半导体行业增长主要依赖智能手机等电子设备的需求&#xff0c;以及物联网、云计算等技术应用的扩增。预计全球半导体行业增长态势有望持续至下一…

python数据运算

算数运算&#xff1a; 比较运算&#xff1a; 赋值运算&#xff1a; 逻辑运算&#xff1a; 成员运算&#xff1a; 身份运算&#xff1a; 位运算&#xff1a; 运算符优先级&#xff1a; 转载于:https://www.cnblogs.com/ne-zha/p/7136920.html

mysql单台跨数据库查询_在MySQL中怎样进行跨库查询?

在MySQL中跨库查询主要分为两种情况&#xff0c;一种是同服务的跨库查询&#xff1b;另一种是不同服务的跨库查询&#xff1b;它们进行跨库查询是不同的&#xff0c;下面就具体介绍这两种跨库查询。一、同服务的跨库查询同服务的跨库查询只需要在关联查询的时候带上数据名&…

宇宙膨胀背后的故事(卅三):宇宙之有生于无

本文来自程鹗科学网博客1969年&#xff0c;卡特和霍金的导师、剑桥大学宇宙学家夏玛&#xff08;Dennis Sciama&#xff09;在哥伦比亚大学讲学。在他话语停顿的间隙&#xff0c;有人突然迸出一句&#xff1a;“也许宇宙就是一个真空涨落&#xff08;vacuum fluctuation&#x…

《自然》 脑机接口新突破 人脑信号转文本准确率达97%

来源&#xff1a;网易智能据国外媒体报道&#xff0c;一个由加州大学旧金山分校的研究团队打造的新型人工智能系统可根据人脑信号来生成文本&#xff0c;准确率最高可达97%。亚马逊和谷歌等科技公司打造的虚拟助手相当先进&#xff0c;语音识别能力比起几年前进步惊人&#xff…

mysql 取月份天数_mysql 之 获取指定月份天数和指定月份上月天数

1.语法DAY(LAST_DAY(CONCAT(nc_date,01)))AS cm_day_cnt, -- 当月天数DAY(LAST_DAY(DATE_SUB((CONCAT(nc_date,01)),INTERVAL 1 MONTH))) -- 上月天数2.解析我的nc_date 是 202004&#xff0c;因此要使用concat 连接01 &#xff0c;形成完整的日期LAST_DAY()函数&#xff0c;获…

tomcat各目录(文件)作用

1.bin bin目录主要是用来存放tomcat的命令&#xff0c;主要有两大类&#xff0c;一类是以.sh结尾的&#xff08;linux命令&#xff09;&#xff0c;另一类是以.bat结尾的&#xff08;windows命令&#xff09;。 重要&#xff1a; 很多环境变量的设置都在此处&#xff0c;例如可…

对外星智能的搜索得到了重大的升级

Photo: iStockphotoRadio antenna dishes of the Very Large Array radio telescope near Socorro, New Mexico.来源&#xff1a;IEEE电气电子工程师我们都曾一度怀疑宇宙中其他地方是否存在智慧生命。加州大学伯克利分校&#xff08;University of California Berkeley&#x…

打开脑科学研究的另一扇窗:脑神经化学活体原位电化学分析新技术

来源&#xff1a;brainnews脑科学是目前国际前沿科技的热点研究领域之一&#xff0c;对脑功能的研究有助于理解人类认知、情感等复杂生理过程的本质&#xff0c;以及神经系统疾病的形成和发展规律。脑神经信号的传递以及代谢过程都离不开化学物质的参与&#xff0c;因此&#x…