字符串常量

news2024/9/20 18:29:47

文章目录

  • 1.内存分布
    • (1) 代码区
    • (2) 全局区
    • (3) 栈区(stack)
    • (4) 堆区(heap)
  • 2.字符串常量的存储
    • 字符数组与字符指针
  • 3.字符串常量内存释放问题
  • 4.字符串常量生命周期
  • 5.字符串常量定义
  • 6.字符数组
  • 7.字符指针
  • 8.内存图
  • 9.补充

1.内存分布

一个编译的C程序占用的内存分为以下几个部分:

1、栈区(stack)—也称自动类型存储区,由编译器自动分配释放,存放函数的参数值,局部变量的值等,例如函数调用结束后自动释放。

2、堆区(heap)—也称动态分配内存区,由程序员分配释放,从分配到程序结束为止,若不释放,程序结束时可能由OS回收,比如malloc分配的内存,free释放的内存。

3、全局区(静态区)(static)—全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域,程序结束后由系统释放。

4、文字常量区—常量字符串放在这里,程序结束后由系统释放

5、程序代码区—编译后的程序代码放在这里。

来看一个具体的C程序

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5Y0D7Pnk-1672642934009)(D:\Typora图片\1240.png)]

下图所示为可执行代码存储时结构和运行时结构的对照图。一个正在运行着的C编译程序占用的内存分为代码区、初始化数据区、未初始化数据区、堆区和栈区5个部分。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hn6T26Mc-1672642934010)(D:\Typora图片\20210106164806527.png)]

(1) 代码区

存放 CPU 执行的机器指令。通常代码区是可共享的(即另外的执行程序可以调用它),使其可共享的目的是对于频繁被执行的程序,只需要在内存中有一份代码即可。

代码区通常是只读的,使其只读的原因是防止程序意外地修改了它的指令。另外,代码区还规划了局部变量的相关信息。

总结:你所写的所有代码都会放入到代码区中,代码区的特点是共享和只读。

(2) 全局区

全局区中主要存放的数据有:全局变量、静态变量、常量(如字符串常量)

全局区的叫法有很多:全局区、静态区、数据区、全局静态区、静态全局区

这部分可以细分为data区和bss区

2.1 data区

data区里主要存放的是已经初始化的全局变量、静态变量和常量

2.2 bss区

bss区主要存放的是未初始化的全局变量、静态变量,这些未初始化的数据在程序执行前会自动被系统初始化为0或者NULL

2.3 常量区

常量区是全局区中划分的一个小区域,里面存放的是常量,如const修饰的全局变量、字符串常量等

在VS下运行结果如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-D1GOTLNM-1672642934010)(D:\Typora图片\ef2cb597dda704b22ef804ec7bdc5fd9.jpeg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FfFm5OTE-1672642934011)(D:\Typora图片\20b6c057019a2ce10f01a9b22e96e6d5.jpeg)]

总结:全局区存放的是全局变量、静态变量和常量

在程序运行后由产生了两个区域,栈区和堆区。

(3) 栈区(stack)

栈是一种先进后出的内存结构,由编译器自动分配释放,存放函数的参数值、返回值、局部变量等。在程序运行过程中实时加载和释放,因此,局部变量的生存周期为申请到释放该段栈空间。

vs运行效果如下

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DieR7Zs0-1672642934012)(D:\Typora图片\2ebcc5b554ce9a53f6cb9376f97c0cef.jpeg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yJRTWvjY-1672642934013)(D:\Typora图片\aa957b05773cef5905a08a8f93dcc002.jpeg)]

(4) 堆区(heap)

堆是一个大容器,它的容量要远远大于栈,但没有栈那样先进后出的顺序。用于动态内存分配。堆在内存中位于BSS区和栈区之间。一般由程序员分配和释放,若程序员不释放,程序结束时由操作系统回收。

vs运行效果如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q4hIAiGg-1672642934013)(D:\Typora图片\382928f8c803df0141546416c216a1af.jpeg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HLvwCwVM-1672642934014)(D:\Typora图片\a631d388aebc9ee52535612afeb8364a.jpeg)]

当我们把几个案例放在一起执行,就可以看到内存将每个区域划分的很有条理。每个区域互不干涉,区域中的数据地址也是非常接近的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zrYpnDbc-1672642934014)(D:\Typora图片\899fd3f84bce419046447e27cb2e517b.jpeg)]


2.字符串常量的存储

首先,毫无疑问,即使是常量(字符串常量)也是要占据空间的。

一般来说,基本类型(整型、字符型等)常量会在编译阶段被编译成立即数,占的是代码段的内存。(代码段是只读的,而且不允程序员获取代码段的地址,所以在c++中,尽量不为const分配数据段的内存,但是一旦取cosnt的地址,就不得不分配了,但是读const的时候,依然是从代码段读取那个立即数)。当然,占代码段的内存一般不在我们常说的“占内存”范围中。代码段不是寄存器。

而字符串常量或基本类型的常量数组占用的是数据段内存。

程序中但凡出现“XXX”形式,这都是代表字符串常量,是要事先存储在程序的只读数据区的。

void test(){
  char name[32] = "hello,world"; // "hello,workd" 存储在程序的只读数据区, name 存储在test函数的栈区。
}

**字符串常量的存储:**字符串常量使用一对双引号括起来的字符序列,与基本类型常量的存储相似,字符串常量在内存中的存放位置由系统自动安排。

由于字符串常量是一串字符,通常被看作一个特殊的一位字符数组,与数组的存储类似,字符串常量中的所有字符在内存中连续存放。所以,系统在存储一个字符串常量时先给定一个起始地址,从该地址指定的存储单元开始,连续存放该字符串中的字符。

显然,该起始地址代表了存放字符串常量首字母的存储单元的地址,被称为字符串常量的值,也就是说,字符串常量实质上是一个指向该字符串首字符的指针常量。

例如字符串**"Hello"的值是一个地址,从它指定的存储单元开始连续存放该字符串的6个字符(‘H’ ‘e’ ‘l’ ‘l’ ‘o’ ‘\n’)**

字符数组与字符指针

如果定义一个字符指针接收字符串常量的值,该指针就指向字符串的首字符,例如:

char sa[]="array ";
char *sp="point ";
printf("%s", sa); //数组名sa作为printf的输出参数
printf("%s", sp); //字符指针sp作为printf的输出参数
printf("%s \n", "string"); //字符串常量作为printf的输出参数

输出:array point string

调用printf()函数,以%s的格式输出字符串时,作为输出参数,数组名sa指针sp字符串"string"的值都是地址,从该地址所指定的单元开始连续输出其中的内容(字符),直到遇到**‘\0’**为止。

由此可见,输出字符串时,输出参数给出的起始位置(地址),**‘\0’**用来控制结束。因此,字符串中其它字符的地址也能作为输出参数。例如:

printf("%s", sa+2); //数组元素sa[2]的资质作为输出参数
printf("%s", sp+3); //sp+3作为起始数组
printf("%s \n", "string" +1 ); //t作为起始输出

输出:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xSW2SrUd-1672642934015)(D:\Typora图片\image-20230101221854877.png)]


字符数组与字符指针都可以处理字符串,但两者之间有重要区别,如:

char sa[]="This is a string";
char* sp="This is a string";

字符数组sa在内存中占用了一块连续的单元,有确定的地址,每个数组元素放字符串的一个字符,字符串就存放在数组中。

字符指针sp只占用一个可以存放地址的内存单元,而不是将字符串放到字符指针变量中去

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hIzvXXVY-1672642934015)(D:\Typora图片\watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBATGl1ZXMyMzM=,size_20,color_FFFFFF,t_70,g_se,x_16.png)]

如果要改变数组sa所代表的字符串,只能改变数组元素的内容。

如果要改变指针sp所代表的字符串,通常直接改变指针的值,让它指向新的字符串。因为sp是指针变量,它的值可以改变,转向指向其它单元。


当定义字符指针后,如果没有赋值,指针的值是不确定的,引用未赋值的指针可能出现难以预料的结果:

char* s;
scanf("%s",s);

没有对指针s赋值,却对s指向的单元赋值,如果该单元已经分配给其他变量,其值就改变了。

所以以下写法str有确定的存储单元,这才是正确的:

char* s,str[20];
s=str;
scanf("%s",s);

为了避免引用未赋值的指针造成的危害,在定义指针时,可先将它的初值置为空,如:char* s=NULL;

一般在使用指针类型后,为避免出现内存泄漏,都需要手动释放内存,如:

char*s =new char[128];
delete []s;
s = NULL;

但如果是像 const char* str 这种指针,则不需要手动释放内存。

这是因为 const char* str 定义的是一个指向常量的指针。

如果str是局部变量,则字符串会随着变量所在的函数的退出而自动释放;如果str是全局变量,则程序退出时才自动释放。

#include<stdio.h>
int main(void){
   //字符串指针
   const char* s = "Hello World!";
   printf("%s\n", s);
   //字符串数组
   char ch[] = "Hello World!";
   printf("%s\n", ch);
   //整型变量和指针
   int* i, a = 233333;
   i = &a;
   printf("%d\n", *i);
   //字符型变量和指针
   char* cha, b = 'a';
   cha = &b;
   printf("%c\n", *cha);
   return 0;
}

输出结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YfSMcio9-1672642934015)(D:\Typora图片\image-20230102092609563.png)]

在处理整型和字符型等时,printf()函数输出时指针变量前需要带上 ***** 号

而处理字符串时,输出时指针变量前则不需要带 ***** 号。

3.字符串常量内存释放问题

#include <iostream>
using namespace std;
char *str1()
{
	char *str="hello world";
	return str;
}
char *str2()
{
	char str[]="hello world"; //str[]在栈上,子函数结束后自动释放内存,返回的其实是首地址
	return str;   //拷贝后,返回和”hello world“无关,返回存在str[]中的内容
}
char *str3()
{
	static char str[]="hello world";
	return str;
}
int main()
{
	char *str=NULL;
	str=str1();
	cout<<"指针指向内存内容:"<<str<<endl;  //输出hello world
	str=str2();
	cout<<"栈内容:"<<str<<endl;    //输出乱码
	str=str3();
	cout<<"静态存储区内容:"<<str<<endl;   //输出hello world
	return 0;
}

字符串常量存放在静态存储区

str1返回指针指向内存首地址,由于字符串常量存在静态区,所以内容不变,还是“hello world”

str2将静态存储区的内容拷贝一份到栈中,由于栈在str2结束时释放栈内存,所以输出为乱码

str3返回存在静态存储区的内容,“hello world”

可以返回一个局部变量的值,也可以返回一个局部静态指针的地址,但不应该返回一个局部自动指针的地址

int get()
{
   int a=152;
   return a;    //可以正确返回
}
int *get()
{
   int a=152;
   return & a;    //无意义
}

4.字符串常量生命周期

字符串char *s=“hello”; 与char s[]=“hello”;,看似都是将hello字符串的地址赋值给指针 *p。

但是前面一个表达式是字符串常量的地址赋值给指针,该指针指向的字符串中的字符是不允许被更改的。

而后面一个表达式是将该字符串的每一个字符赋值给数组,该指针指向的数组的首地址,而数组成员是变量,因此可以允许被更改赋值。

下面讨论关于字符串常量在内存中存在生命周期的的问题。

问题如下:

假如

char *s0="hello";
s0="world";

就是说如果开始s0指针指向“hello”这个字符串这个常量的地址,但是当s0指针指向了“world”符串的时候,那么“hello”这个字符串在内存中的是否会被释放掉,还是会一直存在内存中,直到程序结束。

我们不妨先试着写几行代码,通过运行结果来进行分析:

案例 一:

代码:

#include<stdio.h>
int main()
{
	char *s0,*s1,*s2;
	s0="hello";
	s1="hello";
	s2="hello";
	printf("%p\n",s0);
	printf("%p\n",s1);
	printf("%p\n",s2);
	return 0;
}

运行结果:

三个指针变量的指向的地址都是相同的,如图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TMPzvVIt-1672642934016)(D:\Typora图片\image-20230101215956565.png)]

分析:

通过运行结果我们可以看出,赋给不同字符指针的相同的字符串,所有的指针都指向了相同的地址。

但是案例一由于三个指针变量都在同一个函数,因此不能看出其生命周期,但是可以为下面的案例解释做好铺垫。

案例二:

代码:

#include<stdio.h>
char *s0="hello";
void a(){
	char *s1="hello";
	printf("%p\n",s1);
	s1="world";
}
void b(){
	char *s2="hello";
	printf("%p\n",s2);
	s2="world";
}
int main(){
	char *s3=(char *)0;
	printf("%p\n",s0);
	a();
	b();
	s3="hello";
	printf("%p\n",s3);
	return 0;
}

运行结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ut1JAIfd-1672642934016)(D:\Typora图片\image-20230101220205924.png)]

四个字符指针变量指向的地址还是一样的。

分析:

这就说明问题了,在函数a(),b()中,局部指针变量*s1,*s2都指向”hello“字符串,但是在退出之前有改变指针指向其他字符串,但是两个字符串指针打印出来的地址还是一样的,说明在使用了字符串常量后,该字符串常量并没有在随着函数的结束而消失,而是依旧存在于内存中,因此当其他函数中使用一样的字符串常量时,指向的依旧是跟还是一样的地址。

但是也许有人会问到,因为有在全局字符指针变量 char *s0 =“hello”;指向了该字符串常量,会像全局变量一样,在真个程序运行都不会释放,因此其他函数调使用该字符串常量时才指向了同一地址。确实确实有这种可能,那么我们就可以看下面案例三。

案例三:

#include<stdio.h>
void a(){
	char *s1="hello";
	printf("%0x\n",s1);
	s1="world";
}
void b(){
	char *s2="hello";
	printf("%0x\n",s2);
	s2="world";
}
int main(){
	char *s3=(char *)0;
	a();
	b();
	s3="hello";
	printf("%0x\n",s3);
	return 0;
}

三个字符串指针变量指向的地址还是一样的,如图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IV7a3245-1672642934017)(D:\Typora图片\image-20230101220730477.png)]

分析:

当我们去掉全局指针变量后,其结果依旧是*s1,*s2,s3 三个指针变量指向的地址依旧是没有变。

在运行完a(),b()两个函数之后,我们再将”hello”赋值给空指针s3指针,其指向地址与*s1,*s2都一样的。

因此我们可以得出结论:一旦有字符串常量在运行期间创建,就会在内存中一直保持到程序结束,当使用相同的字符串常量的时候,不会再创建字符串常量,而是指向之前的那个。因此字符串常量是贯穿整个程序的生命周期的。


附:既然说到这里了,那就再多说一点。

案例:当将 char* s0 改为char s0[ ]时。

代码:

#include<stdio.h>
char s0[]="hello";
void a(){
	char *s1="hello";
	printf("%0x\n",s1);
	s1="world";
}
void b(){
	char *s2="hello";
	printf("%0x\n",s2);
	s2="world";
}
int main(){
	char *s3=(char *)0;
	printf("%0x\n",s0);
	a();
	b();
	s3="hello";
	printf("%0x\n",s3);
	return 0;
}

运行结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-U8NPnT08-1672642934017)(D:\Typora图片\image-20230101221124047.png)]

s0与s1 、s2、 s3指向的地址不同。

分析:

造成这样的结果的原因是因为char s0[]="hello",而s0指向的是该数组的首地址,而不是字符串的首地址。

s1、 *s2、 *s3都是指向字符串的首地址,因此不同。

#include <stdio.h>

int main(int argc, char *argv[])
{
    printf("Hello C-Free!\n");
    
    //定义一个数组变量,用字符串常量初始化其值 。 
    char a[] = "123";          
    //定义一个字符指针,再定义一个字符串常量,指针指向的常量首地址 
    const char* b = "321";    
    const char* c = "321";    
    //打印变量在内存里的地址,栈区【高地址->低地址】 
    printf("%d,%d,%d\n",&a, &b, &c);//6356772,6356768,6356764
    //打印指针的首地址,b和c相同因为都指向同一常量区 
    printf("%d,%d,%d\n",a, b, c);    //6356772,4206607,4206607
    //打印内容 
    printf("%s,%s,%s\n",a, b, c);    //123,321,321

    //从b内存拷贝3个字节给a变量,正常 
    memcpy(a, b, 3); 
    //从a内存拷贝3个字节给a常量指针,编译失败或运行失败,常量不可修改 
    memcpy(b, a, 3); 

    printf("%s,%s,%s\n",a, b, c);    //123,321,321
    return 0;
}

5.字符串常量定义

定义:用双引号(“”)括起来的0个或者多个字符组成的序列。

存储:每个字符串尾自动加一个 ‘\0’ 作为字符串结束标志。

字符串常量在内存的常量存储区是按顺序存储的,如:

char* a = "123";
char* b = "456";
char* c = "456";

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eYbwxDPW-1672642934018)(D:\Typora图片\990943-20210713165252108-1379805600.png)]

定义a时,存储一个“123\0”;

定义b时,判断存储区是否有"456\0",发现没有则在后面追加"456\0";

定义c时,判断存储区是否有"456\0",发现有,则不再存储,此时b和c两个指针存储的都是"456\0"这片内存地址

既然是常量,那么不可被修改,所以memcpy(b, a, 3);是错误的。

6.字符数组

char a[] = "123";

首先声明一个字符数组a,大小没有确定,但是将一个字符串常量“123\0”赋值给了a,故a的length就是4个字节。【注意“123\0”并没有存储在常量区】

注意a归根结底是一个数组,数组是一个变量,不是指针,虽然可把a当做一个指针,因为它指向数组的首地址,但归根结底不是指针。

正因为a是变量,所以a能够修改其存储的值。

比如:

int main(){
    char a[]="123";
    a[0]='a';
    printf("%s\n",a);
}

输出结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sRbtmf46-1672642934018)(D:\Typora图片\image-20230101193318240.png)]

7.字符指针

const char* b = "321";

既然名字是字符指针,那么它一定是个指针,指针存储地址。

故解读这句就是:

首先声明一个字符指针b,然后定义一个字符串常量"321\0"。

字符串常量存储在常量区,b存储在栈区,b存储的值是字符串常量"321\0"的地址。

这里用到了const,在C语言里不加const也行,C++里不加会有个警告,但不影响编译。但是建议加上const,能够让程序员一眼就知道此指针指向的是常量,也就是最终内容无法修改。

虽然最终指向不能修改,但是指针自身的取值,是可以修改的,即可修改指针指向的地方。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Txr2Qw9f-1672642934018)(D:\Typora图片\990943-20210713173550898-1076816549.png)]

8.内存图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oy3LXGsc-1672642934019)(D:\Typora图片\990943-20210713174838404-1399769579.png)]

所有存储类型代码区、常量区、静态区(全局区)、堆区、栈区,只有栈是从高地址往低地址存储,其他都是低地址往高地址存储。

9.补充

来分析几段代码。

代码:test0.c

#include <stdio.h>
#include <stdlib.h>
char* toStr() 
{
	char *s = "hello word!";
	return s;
}
int main(void) 
{
	printf("%s\n", toStr());
}

运行结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SmvEyuWA-1672642934019)(D:\Typora图片\image-20230101223619968.png)]

运行没有任何问题,因为 “hello world” 是一个字符串常量,存放在文字常量区,把该字符串常量存放的地址赋值给了指针 s,toStr 函数退出时,该该字符串常量所在内存不会被回收,故能够通过指针顺利无误的访问。

代码:test1.c

#include <stdio.h>
#include <stdlib.h>
char* toStr()
{
	char s[] = "hello word!";
	return s;
}
int main(void)
{
	printf("%s\n", toStr());
}

编译运行结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5gGkLUoq-1672642934019)(D:\Typora图片\20210108200224964.png)]

调用 toStr 函数,定义了一个局部变量( char [] 型数组),该局部变量存放在栈中,当 toStr 函数退出时,栈要清空,局部变量的内存也被清空了,所以这时的函数返回的是一个已被释放的内存地址,出现段错误。

如果函数的返回值非要是一个局部变量的地址,那么该局部变量一定要申明为static类型

代码:test2.c

#include <stdio.h>
char *returnStr()
{
    static char p[]="hello world!";
    return p;
}
int main()
{
    char *str=NULL;
    str=returnStr();
    printf("%s\n", str);                                                                          
    return 0;
}

运行结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GveRoy2j-1672642934020)(D:\Typora图片\image-20230101223914993.png)]

综合性代码:

#include <stdio.h>

//返回的是局部变量的地址,该地址位于动态数据区,栈里                                                                             
char *s1()
{
    char p[] = "Hello world!";

    printf("in s1 p=%p\n", p);
    printf("in s1: string's address: %p\n", &("Hello world!"));

    return p;
}

//返回的是字符串常量的地址,该地址位于静态数据区
char *s2()
{
    char *q = "Hello world!";

    printf("in s2 q=%p\n", q);
    printf("in s2: string's address: %p\n", &("Hello world!"));

    return q;
}

//返回的是静态局部变量的地址,该地址位于静态数据区
char *s3()
{
    static char r[] = "Hello world!";

    printf("in s3 r=%p\n", r);
    printf("in s3: string's address: %p\n", &("Hello world!"));
    return r;
}
int main()
{
    char *t1, *t2, *t3;

    t1 = s1();
    t2 = s2();
    t3 = s3();

    printf("\nin main:\n");
    printf("p = %p\nq = %p\nr = %p\n", t1, t2, t3);

//  printf("%s\n", t1);		/* 运行会出现段错误,先屏蔽 */
    printf("%s\n", t2);
    printf("%s\n", t3);
                                                                                                                                                   
    return 0;
}

运行结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fSsNT4Yu-1672642934020)(D:\Typora图片\image-20230101223952538.png)]

根据运行结果我们就很清楚了,这里不再赘述。


🔖 部分参考文章:

(37条消息) 关于字符串常量在内存中的生命周期_w_16822的博客-CSDN博客

(39条消息) 【C语言入门】笔记十 (指针中)_Liues233的博客-CSDN博客_假设字符数组sa为一个英文字符串,设计程序,当用户用键盘输入字符串sa后,将

(40条消息) C语言—内存的管理和释放_^不加糖^的博客-CSDN博客_c语言释放内存

请添加图片描述

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

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

相关文章

Object类

文章目录面试题&#xff1a;和equals()的区别回顾&#xff1a;和equals重写后的调用重写equals方法的原则答案toString()方法面试题&#xff1a;和equals()的区别 回顾&#xff1a;和equals &#xff1a;运算符 1、可以使用在基本数据变量和引用数据变量中 2、如果比较的是基…

Model Animation动画页签

1、Animation动画页签 当我们选中包含动画剪辑的的模型时&#xff0c;该页签将显示动画设置相关的内容 动画剪辑是Unity动画的最小构成元素&#xff0c;代表一个单独的动作 当美术同学做好动画导出时建议将模型和动画文件分别导出 导出包含网格信息不包含动作信息模型导出不…

【大数据】CentOS7环境下安装MySQL数据库

文章目录1.安装mysql1.1 删除CentOS系统自带数据库1.2 开始安装mysql1.3 启动mysql服务&#xff0c;并设置密码1.4 授权所有外部用户连接MySQL&#xff08;了解&#xff09;2.客户端操作mysql常见查询操作解决汉字乱码问题创建操作1.安装mysql CentOS7自带的是Mariadb&#xf…

Prometheus学习和整理

是基于时序数据库的开源监控告警系统,非常适合对K8S集群的监控,它通过HTTP协议周期性的抓取被监控组件的状态,任意组件只要提供对应的HTTP接口就可以接入监控, 特点: 支持多维数据模型&#xff1a;由度量名和键值对组成的时间序列数据 内置时间序列数据库TSDB 支持PromQL查…

AI修复照片

一、前言 最近闲来无事&#xff0c;翻了翻以前的老照片&#xff0c;看着多年前的老照片&#xff0c;感慨万千&#xff0c;仿佛又回到了以前的青春岁月。 只可惜青春易逝&#xff0c;无法重来。意气风发&#xff0c;头角峥嵘的画面只能永远地留存在相片之中了。只叹当时没有多拍…

Windows下数据资源公开访问之环境搭建方法(2023.1.2)

Windows下数据资源公开访问之环境搭建方法&#xff08;2023.1.2&#xff09;1、需求分析2、常用的解决方案2.0 前提环境&#xff08;Java Node&#xff09;2.1 方案一&#xff1a;利用现有服务器容器&#xff08;以Tomcat为例&#xff09;2.1.1 下载Tomcat并解压2.1.2 配置系统…

数据结构-考研难点代码突破(C++实现有向图最短路径算法(Dijkstra,Floyd-Warshall算法)图解操作细节(引自C语言中文网))

以代码的方式复习考研数据结构知识点&#xff0c;这里在考研不以代码为重点&#xff0c;而是以实现过程为重点 文章目录1. 最短路径2. 单源最短路径ⅠDijkstra算法C代码3. 多源最短路径Ⅰ Floyd-Warshall算法C代码1. 最短路径 图的生成树针对的是无向图&#xff0c;图的最短路…

error ‘for’ loop initial declarations are only allowed in C99 mode的报错原因和两种解决办法

error: ‘for’ loop initial declarations are only allowed in C99 mode的报错原因和两种解决办法 for(int i0;i<5;i) { … } 错误&#xff1a;使用gcc编译代码报错 &#xff1a;error: ‘for’ loop initial declarations are only allowed in C99 mode note: use …

Spark02: Spark三种任务提交方式

1. 直接在IDEA中执行&#xff0c;方便在本地环境调试代码 2. 使用spark-submit提交到集群执行【实际工作中使用】 3. 使用spark-shell&#xff0c;方便在集群环境调试代码 比如&#xff1a;需要连接数据库&#xff0c;无法在本地调试的情况。 spark-shell 实现了用户可以逐…

流程控制之for循环练习

目录练习案例1. for创建20用户2. for ping测试指网段的主机3. 使用for实现批量主机root密码的修改练习案例 1. for创建20用户 用户前缀由用户输入 用户初始密码由用户输入 例如&#xff1a;test01,test10 #!/bin/bash ######################### #File name:userCreate.sh #…

[学习笔记]2021韩顺平一周学会Linux

文章目录视频链接&#xff1a;第1章&#xff1a;Linux开山篇-内容介绍1.1 本套Linux课程内容1.2 Linux使用的地方1.3 Linux应用的领域第2章&#xff1a;Linux基础篇-Linux入门&#xff1a;2.1 Linux介绍2.1.1概述2.2 Linux和Unix的关系2.2.1 Unix是怎么来的2.2.2 Linux是怎么来…

【阶段一】Python快速入门06篇:正则表达式-re 模块

本篇的思维导图: 正则表达式-re 模块 正则表达式(Regular Expression)是一种文本模式的描述方法。例如,\d是一个正则表达式,表示一位数字字符,即任何一位0到9的数字。 在 Python 语言中re 模块提供了全部的正则表达式函数,例如:compile 函数。 compile 函数 compile 函…

Qt CSV文件的创建,读写操作

文章目录一.CSV文件介绍二.创建CSV文件三.写入CSV文件四.读取CSV文件一.CSV文件介绍 逗号分隔值&#xff08;Comma-Separated Values&#xff0c;CSV&#xff0c;有时也称为字符分隔值&#xff0c;因为分隔字符也可以不是逗号&#xff09;&#xff0c;其文件以纯文本形式存储表…

基于ASP.NET MVC的运动用品网上销售系统

摘要 随着现代都市生活节奏的不断加快、网络覆盖面的日益扩大&#xff0c;越来越多的人们加入了网上购物的行列。如今&#xff0c;网购已经成为人们生活的一部分。本系统主要是使用 B/S架构开发出的一个基于ASP.NET的运动用品网上销售系统。前台页面使用htmljscss&#xff0c;S…

Freemarker指令语法

基础语法种类 1、注释&#xff0c;即<#-- -->&#xff0c;介于其之间的内容会被freemarker忽略 <#--我是一个freemarker注释-->2、插值&#xff08;Interpolation&#xff09;&#xff1a;即..部分,freemarker会用真实的值代替{..}部分,freemarker会用真实的值代…

十一、中间件的使用

Express的应用本质上就是调用各种中间件&#xff0c;中间件指的是业务流程中的中间处理环节&#xff0c;服务器的生命周期一般是 接收 —— 处理 —— 响应&#xff1b;那么中间件就充当处理的角色&#xff0c;它其实就是一个函数&#xff0c;该函数除了能够访问请求对象req和响…

TC275——02板卡简单介绍

前部 核心&#xff1a;英飞凌 32位 AURIXTC275 TriCore核 开发工具&#xff1a; AURIX™Development Studio、FreeEntryToolchain CPU&#xff1a; 最大频率&#xff1a;200M外部晶振&#xff1a;20MFPU&#xff1a;支持封装&#xff1a;LQFP176-22 FLASH&#xff1a;4M D…

高并发系统设计 -- 性能测试

响应时间&#xff1a;是客户发出请求到得到响应的整个过程的时间。 网络传输时间&#xff1a;N1N2N3N4应用服务器处理时间&#xff1a;A1A3数据库服务器处理时间&#xff1a;A2响应时间&#xff1a;N1A1N2A2N3A3N4 负载&#xff1a;模拟业务操作对服务器造成压力的过程&#x…

shell-函数与数组

1.编写函数&#xff0c;实现打印绿色OK和红色FAILED 判断是否有参数&#xff0c;存在为Ok&#xff0c;不存在为FAILED [rootcotenos day06]# vim colour.sh #!/bin/bash test(){if [ -z $1 ];thenecho -e "\033[31m FAILED \033[0m"elseecho -e "\033[32m …

git tutorial

最近老板要搞retreat 需要做一个分享&#xff0c;正好把分享的内容作为博客记录一下。 说起git&#xff0c;那就不得不提GitHub。 GitHub 最开始是作为一个面向开源以及私有项目的管理平台。它可以存储代码&#xff0c;文档&#xff0c;数据等等。目前最常用将其作为一个代码…