在C语言当中字符串数组和字符串指针都是用来指向或者存储一段string的。但是栈上字符串指针指向的内容确实不可以修改的。
本博客参考文献:
字符串数组和指针对于sizeof与strlen的区别与影响:
https://blog.csdn.net/cx2479750196/article/details/81288989
字符串数组
//字符串数组
#include <stdio.h>
#include <string.h>
int main(){
char str1[] = "123456";
char str2[]={'1','2','3','4','5','6','\0'};
char str3[]={'1','2','3','4','5','6'};
int len1 = strlen(str1);
int size1=sizeof(str1);
printf("%d, %d\n",len1,size1);
//结果 6,7
int len2 = strlen(str2);
int size2=sizeof(str2);
printf("%d, %d\n",len2,size2);
//结果 6,7
int len3 = strlen(str3);
int size3=sizeof(str3);
printf("%d, %d\n",len3,size3);
//结果 随机数,6
return 0;
}
可以发现使用不同的方式进行初始化的时候,直接使用""方式进行初始化时候,会隐式的加入’\0’来作为结束符。并且使用单独赋值str3类似的方式的时候,因为是没有添加结束符号的,所以在使用strlen时,会一直寻找结束符,会得到一个随机的数字。
字符串指针
//字符串数组
#include <stdio.h>
#include <string.h>
int main(){
char* str1 = "123456";
int len1 = strlen(str1);
int size1=sizeof(str1);
printf("%d, %d\n",len1,size1);
//结果 6,8
return 0;
}
可以发现如果使用指针来指向一个字符串的时候,strlen依然是从指向的地址开始,然后寻找结束符。但是sizeof()用来求变量 、数组、对象、结构体等所占空间的大小是,所以sizeof一个字符串指针的时候返回的时候char*的大小,在32位机器里为4,在64位机器里为8。
字符串数组和字符串指针的修改
在定义为字符串数组和字符串指针后,如果我们想要修改里面的一些值,会出现以下情况:
char* str1 = "123456";
char str2[] = { '1','2','3','4','5','6','\0' };
// 尝试修改字符串指针指向的字符串中第1位的值:失败
str1[1] = '0';
// 尝试字符串第1位的值:成功
str2[1] = '0';
可以发现用char* 指针指向的值居然是不可改变的,char[]的值可以正常改变。
原因:char[] 存储在全局数据区或栈区,char*字符串存储在常量区。全局数据区和栈区的字符串(也包括其他数据)有读取和写入的权限,而常量区的字符串(也包括其他数据)只有读取权限,没有写入权限。所以尝试对在常量区的字符串进行赋值时错误的。
字符串指针指向堆上开辟的空间
有一种情况,我们需要对字符串指针指向的字符串进行修改。那就需要使用内存分配。使用malloc进行内存开辟,应为该函数的返回值为void,所以需要进行类型的强制转换。空间使用完毕之后,需要使用free将内存空间进行清理,换给操作系统。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char* str1="Hello"; \\这样声明的变量,变量在栈上
char* str2=(char*) malloc((sizeof(str1)+1)*sizeof(char)); \\这样声明的变量,变量在堆上
if(str2==NULL){
printf("error");\\需要检验是否开辟空间成功
return 1;
}
strcpy(str2,str1);\\进行赋值
printf("%s\n",str2); \\输出结果:Hello
str2[0]='h';
printf("%s\n",str2);\\输出结果:hello
free(str2); \\释放开辟的空间
str2=NULL;
return 0;
}