一、字符串的双引号问题
字符串的双引号做了3件事:
- 申请了空间(在常量区),存放了字符串 ;
- 在字符串尾加上了’/0’ ;
- 返回地址。
char *str = “hello”; /* 把地址赋值给str */
/* "hello"表达式使用的值是这些字符所存储的地址(在常量区),而非这些字符本身。
* 注:str保存的字符串常量的首地址,*(str+i)是具体的第i-1个字符,因为是常量,
* 不能使用*(str+i) = 'H'改变字符串,但是执行 str = 'world' 可以,这是改变指针的指向。
*/
二、字符数组与字符串的关系
char str[10] = “hello”; //正确
char str[10]; a = “hello”; //错误 /* 这说明数组的地址是常量 */
/* 在C语言中没有专门的字符串变量,如果想将一个字符串存放在变量中以便保存,
* 必须使用字符数组,即用一个字符型数组来存放一个字符串,数组中每一个元素存放一个字符
*/
char str[] = "hello"; <=> char str[6] = {'h','e','l','l','o','\0'}; //保存于栈中
三、二维数组定义字符串
const char str[][5] = {"ling", "yi", "er", "san", "si",
"wu", "liu", "qi", "ba", "jiu"};
/* 一维要声明里面具体某个单元的个数,在定义之时初始化二维可以不写 */
/* 可理解为字符数组的数组 */
const char *str[] = {"ling", "yi", "er", "san", "si",
"wu", "liu", "qi", "ba", "jiu"};
/* 第二种的好处是不用声明一维的个数,这是指针数组或者字符串数组;该数组名可以传递给二重指针 */
/* 可理解为字符指针的数组 */
四、字符数组与字符指针
/* 数组的类型是由该数组所存放的东西的类型以及数组本身的大小决定的,
* 字符串常量的类型可以理解为相应字符常量数组的类型
*/
char str[] = "hello";
/* 对于字符数组,它只分配一段内存,&str <=> &str[0] <=> str,地址都是字符串所在的地址;
/* 对于数组变量,可以使用变量名str来索引变量中的内容,其实数组名可以理解成数组变量退化的指针,
* 并且指向数组的开头,既然把它理解成指针,那么它的值肯定是地址了,所以它的值和上面两个也一样*/
char* str = "hello";
/* 对于字符指针,它会分配两段内存,&str <!=> &str[0] <=> str,&str是指针变量的地址
因此字符串是字符数组或者是指针,内存实现都一样的。 数组名是一个指针。