字符串在程序中很常见,和整数、小数、字符其他数据类型一样,是代码中必不可少的一部分。可是字符串却又和其他类型不完全一样,还有自己的个性。
下面直接通过一段代码来看。
定义了一个字符1.一个字符串1,然后将他们打印出来,打印结果如下:
从打印的结果来看,二者并没有差别。
下面接着打印一下这两个的长度,使用sizeof()函数,分别计算s1和s2的长度并打印出来。
可以看到字符s1的长度是1,字符串s2的长度是2, 在内存中查看s1和s2的存储地址
从内存存储位置可以看出字符s1占了一个字节,字符串s2占了两个字节,后面的一个字节是空的。所以通过sizeof()函数计算出来s2所占空间的大小是2。
在这里要顺便说一下计算长度的函数sizeof() 和 strlen(),这两个都可以计算字符串的长度,但是 sizeof() 函数计算出来的是实际占据空间的大小,而strlen()计算出来的是有效字符的长度。所以对于字符串而言sizeof()函数计算的结果会比strlen()计算出来的结果大1。
比如这里定义一个字符串“abc”,然后分别使用这两个函数计算它的长度。
char s2[]="123";
printf( " %d %d\r\n\r\n\r\n", sizeof(s2),strlen(s2));
从打印的结果可以看出,字符串有效长度是3,但是字符串所占空间大小是4。
接下来看看对字符的操作和字符串的操作是否一样。
对字符s1和字符串重新赋值,此时编译器报错,不允许直接字符串s2赋值,这是由于字符串在内存中是按照字符数组来存储的,也就是存储在一系列连续的存储空间内,每一个字符占一个字节。所以不能对字符串整体进行操作,要改变字符串的值,只能像修改数组的值一样,每一位单独操作。
所以这里要改变字符串中存储的字符,就直接给数组的第0位赋值。
可以看到对s1和s2的第0位重新赋值后,内存中存储的数据也发生了变化,和打印出来的数据一样。
注意内存中存储的字符是以ASCII码的方式存储的,而串口打印出来的直接就是字符。ASCII码 0x31 对应的字符就是1,ASCII码 0x32 对应的字符就是2。
同样将一个字符赋值给另一个字符时可以正常赋值,但是不能将一个字符串直接赋值给另一个字符串。
要将字符串赋值给另一个字符串时,也需要向数组一样,一位一位的赋值。
打印结果如下
在内存中查看
内存中的结果和打印的结果一致。接下来在看一个例子,将s1和s2传递到其他函数中进行操作。
char s1='1';
char s2[]="1";
void change1(char s3)
{
s3 = s3 + 1;
printf( "s3 -> %c \r\n", s3 );
}
void change2(char s4[])
{
s4[0] = s4[0] + 1;
printf( "s4 -> %s \r\n", s4 );
}
void main( void )
{
//省略无关代码
while( 1 )
{
change1(s1);
change2(s2);
printf( "s1 -> %c s2 -> %s\r\n\r\n\r\n", s1,s2 );
delay_ms( 5000 );
}
}
在将s1和s2的值传递到外部函数之后,在外部函数里面对字符加1,然后打印出来,从外部函数退出之后,接着打印s1和s2的值。
打印结果如下
s1的值是字符1,然后将s1传递给s3,然后s3加1之后,打印出字符2,符合代码逻辑。
s2的值是字符串1,然后将s2传递给s4,然后s4加1之后,打印出字符2,符合代码逻辑。
接下来从子函数退出后,分别打印s1和s2的值,可以发现s1的值依然是1,但是s2的值却变成的2。
如果程序一直执行的话,会发现s1和s3的值一直没有变,但是s2和s4的值却一直在增大。
这是什么原因呢?字符串传递给子函数后,字符串本身也会被子函数改变?
为了一探究竟,下面开始单步调试,同时查看内存中数据的变化情况。
当代码执行到 s3 = s3 + 1;这一行时,系统中s3的存储位置为A,数值为字符’1’,此时s1的存储位置为0x00000C。下面对s3执行加1操作。
执行完加1操作之后,s3的值变成了字符’2’,此时s1的值依然是字符’1’,未发生变化。
接下来执行第二个函数,对字符串s4进行操作。
可以看出当执行到 s4[0] = s4[0] + 1; 这一行时,此时s4在内存中的地址是0x00000D,而s2的内存地址也是0x00000D,难道s4和s2是一个地址吗?继续执行程序观察。
当对s4中第0位的字符执行完加1操作之后,s4中的字符变成了’2’,而此时s2中的字符值也变成了’2’,说明s4和s2在内存中的确是同一个地址。
两个函数执行完成之后,继续打印s1和s2的值,由于在子函数执行的时候,s1的地址上值未发生改变,s3的值是s1的值加1,s2和s4指向的是同一个地址,s4每次循环都要加1,所以s2的值每次也会加1。
为什么对于字符没有发生变化,而字符串发生了变化?这是因为在C语言中字符串属于引用类型,而字符属于值类型?
值类型包括:byte,short,int,long,float,double,decimal,char,bool 和 struct。
引用类型包括:string 和 class。
系统对于值类型操作时,如果将一个值类型赋值给另一个值类型,那么系统就会重新开辟一个空间,然后将值复制一份,然后再将值存入新开辟的空间中。这样当操作新数据的时候,不会影响以前的数据,因为两个值都在自己的存储空间中。
系统对于引用类型操作时,如果将一个引用类型赋值给另一个引用类型,系统检测到这两个值如果全完一样的话,那么系统就不会重新开辟空间给新的引用类型,而是直接让新的引用类型地址指向旧的引用类型,让这两个值公用同一个内存空间,也就是相当于给一个地址空间起了两个名字,这样改变任意一个值时,地址空间内的值也会发生变化。
所以在使用字符串的时候,一定要注意这一点,这是它和其他类型值的最大区别。
如果不加小心,在传递值的过程中,数据很容易出错。
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/qq_20222919/article/details/120658370
内容来源于网络,如有侵权,请联系作者删除!