C语言字符串


字符串

    c 语言没有专门用于存储字符串的变量类型,字符串都被存储在 char 类型的数组中。数组由连续的存储单元组成,字符串中的字符被存储在相邻的存储单元中,每个单元存储一个字符,c 语言用数组末尾的字符 \o 标记字符串的结束。

      c 中的字符串一定是以空字符结束,这意味着数组的容量必须至少比待存储字符串的字符数多 1,以上图中有14个存储单元,却只能存储13个字符,剩下一个字节留给空字符。      

字符串常量

     用双引号括起来的内容称为字符串的字面量,也叫做字符串常量。双引号中的字符和编译器自动加入末尾的 \0 字符,都作为字符串存储在内存中,如:” hello world ! ” 、” good morning “ 、 “ i am a student ” 都是字符串字面量。另外注意一点,你的字符串字面量之间如果没有间隔,或用空白字符分隔,c 会自动将它们串联起来。

#include<stdio.h>
int main(void)
{
	char a[]="hello ""world "   "!";
	char b[]="hello world !";

	printf("a[]=%s     b[]=%s\n",a,b);
	
	return 0;
	
}

它们的输出是相同的:

字符串变量

我们字符串变量一般有两种方法创建,指针或者是数组

#include<stdio.h>
int main(void)
{
	char a[]="hello world !";   //数组
	char* b=" hello world !";   //指针
	
}

    数组形式( a [ ] )在计算机的内存中分配为一个内含14个元素的数组,每个元素初始化为字符串字面量对应的字符。通常,字符串都作为可执行文件的一部分存储在数据段中。当把程序载入内存时,也载入了程序中的字符串。字符串存储在静态存储区中,但是,程序在开始运行时才会为该数组分配内存。此时才将字符串拷贝到数组中,此时字符串有两份,一个是在静态内存中的字符串字面量,另一个是存储在 a[ ] 数组中的字符串。

文字有点晦涩,我们结合图看看  

 指针形式( *b )也使得编译器为字符串在静态存储区预留14个元素的空间。一旦开始执行程序,它会把字符串地址存储在指针变量中。该变量指向该字符串的首字符。 

其实不用关心太多,你只要知道,初始化数组把静态存储区的字符串拷贝到数组中,你的数组得到的只是它的副本,而初始化指针只把字符串的地址拷贝给指针,你得的是静态存储区字符串的地址。

数组和指针的选择:

     那么我们用数组还是用指针呢?它们一个存着地址一个存着副本,所以肯定是有差别的对吧,我们精简的了解一下,因为书上真的很复杂写了一大堆的例子,我们提取一下精华:

     字符串字面量是 const 的数据(常量),由于 *b 指向这个 const 数据,所以实际上 b 是 const  char * b ,但是由于历史的原因,编译器接受不带 const 的写法,这意味这不能用 b 改变它指向的数据,但是仍然可以改变 b 的值,就是让 b 指向别的位置。如果把一个字符串字面量拷贝给一个数组,就可以随意改变数据,除非把数组声明为 const,数组元素是变量,但是数组名不是变量。

#include<stdio.h>
int main(void)
{
	char a[]="hello world !";  //数组
	a[0]='H';
	printf("a[]=%s\n",a);
	
	char* b="hello world !";   //指针
	b[0]='H';   
	printf("*s=%s\n",b);
	
	return 0;
	
}

         

我用的是 Dev -C++ ,在我电脑上编译它过了,但是这个指针形式并没有输出,这就很好的证明了上面说的对吧,你用指针你不能修改字符串字面量(字符串常量),因为你的指针是 const char *,所以你可以在把指针初始化为字符串字面量时使用 const 限定符:const char * b,书上推荐我们这样用,这也是比较安全的做法,看见 const 我们就知道不能去修改它。总之,初始化数组把静态存储区的字符串拷贝到数组中,而初始化指针只把字符串的地址拷贝给指针,如何选择取决于你想用程序做什么,如果你要去构造一个字符串→数组,如果你要处理一个字符串→指针。

补充

       再说一下指针,就是当你用多个指针初始化的字符串字面量是一样的,它们得到的是同一个地址,编译器可以使用内存中的一个副本表示所以完全相同的字符串字面量。

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

你看它们的地址是不是一模一样

 所以你有没有懂懂一点点这个(你初始化指针是 const ),如果允许你修改的话:

    char* a="hello world !"; 
    char* b="hello world !"; 
    char* c="hello world !"; 
    
    printf("a= %p\n",a);
    a[0]='y';               
    printf("b= %p\n",b);
    printf("c= %p\n",a);

那后面两个输出都变成“ yello world ”,如果编译器使用这种单次副本表示法,并允许 a[ 0 ] 修改 ‘ h ’,那将影响所有使用该字符串的代码。而把数组初始化为字符串字面量却不会导致类似问题,因为数组获得的原始字符串的副本。总之,如果你打算修改字符串,就不要用指针去初始化
    

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值