字符串在C语言中实际是字符数组,由于C比其余大多数语言更底层,他并无提供字符串这个数据类型,而是采用类似的东西代替,这就是以字符为元素的数组。数组
char *s="PPYY";ide
上面这个字符串(咱们也把它称为字符串字面值),C会把它做为数组进行操做,函数
char s[]={'P','P','Y','Y'};指针
因此采用s[0],s[1]访问这个字符串是被容许的,可是须要很是清醒的是,字符串字面值是不能被修改的,由于字符串字面值和字符数组在内存当中的工做方式是不一致的。内存
咱们以Linux系统为例,粗略说说为何他们的工做方式不一致,下图是简略的内存结构图:字符串
局部变量区域 |
栈 |
无序组合 |
堆 |
全局区 |
|
只读存储区 |
常量区 |
代码区 |
/*字符串字面值的工做工做方式*/
it
一、字符串字面值 "PPYY"先是存放在常量区,存放的样子以下:编译
P |
P |
Y |
Y |
\0 |
(尾部有个\0 ,是字符串的在内存中的结束符,由于C语言并不知道字符串何时结束。)table
二、而后在栈上建立s这个指针变量,用以存放指向常量区"PPYY"字面值的地址。class
这就解释了为何咱们尝试修改字符串字面值的时候,程序会报错,由于字符串字面值是存放在常量区的。
/*字符数组的工做方式*/
一、"PPYY"这个字符串字面值仍然先是存放在常量区。
二、在栈上建立一个字符数组,数组的长度和数组元素都和先前的字符数组一致。
这个时候咱们在程序中操做这个字符数组的时候,实际上是操做的这个字符串字面值在栈空间中的字符数组副本。
这里咱们顺着这个思路理清楚 char *s这个指针变量和char s[]这个数组变量的不一样之处在什么地方。
char *s这个s是存放的常量区"PPYY"字面值的地址;而char s[]这个s表示栈空间中数组第一个元素的内存地址。上面两个描述,一个是存放,一个表示,由于char *s在初始化的时候,是在内存中分配了char类型的地址变量空间的。而char s[]在初始化的时候,是没有分配内存空间的,只是程序在编译的时候,会把这个s替换成数组第一个元素的内存地址。
char s[]和char *s在做为函数形参时效果是同样的,即void func_name(char s[])和void func_name(char *s)是等价的,可是此时的数组变量会退化成指针变量,做为数组变量,咱们能够经过sizeof()运算符判断数组的长度,可是指针变量咱们只能获得这个指针变量自己的长度。