C char*, char [], char** and C++ string

char arr[](字符数组,C类型字符串)

  1. C语言中的字符串的概念:以NULL字节结尾的零个或者多个字符。而字符数组可以不以'\0'结束,而且不能为空。
  2. 字符串通常存在字符数组中,这也是C语言中没有显式的字符串类型的原因。
  3. 因为字符串以NULL结束,所以字符串内部不能有NULL字节。
  4. 为什么选择NULL作为字符串的终止符,因为它不是一个可打印的字符。

如下所示,是char str[],即字符数组的定义。str是局部变量,存放在栈里面。

1
2
3
char str1[] = "hello";
char str2[] = {'h', 'e', 'l', 'l', 'o', '\0'};
char str3[] = {'h', 'e', 'l', 'l', 'o'};

char*(字符指针)

  1. char*是一个指针,指向一个char,理论上来说,它并不是一个数组。
  2. char *ptr;并不为它指向的内容分配内存,而是只分配一个char *大小的内存存放指针变量ptr
  3. char arr[10];是一个数组,不是一个指针,char *char[10]不是一个类型。

如下所示:

1
2
3
4
5
6
7
char str[] = "hello world";
char *ps = str;
// char *类型的指针ps指向一个字符数组。

char c = 'x';
char *pc = &c;
// char *类型的指针pc指向一个字符。

char**(指向字符指针的指针)

char**是一个指针,指向一个指向char的指针,它可以指向一个指针数组。如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include "stdio.h"
#include "stdlib.h"


int main() {

char *arr[] = {
"hello",
"world",
"hi"
};

// arr是一个数组,数组的元素是`char*`类型。
// 数组名可以看成指向数组首元素的指针。
char **p = arr;

printf("%s\n", *p);
printf("%s\n", *(p+1));

printf("%c\n", *(*(p+1)+2));

}

pchar**类型的元素,即指向char*类型的指针,p+1获取下一个指向char*的指针;*pchar*类型的元素,即指向char类型的指针,指向第一个字符串的第一个字符,*(p+1)指向第二个字符串的第二个字符;**pchar类型的元素,是第一个字符串的第一个字符,*(*(p+1)+2)指向第二个字符串的第三个字符。
事实上,这个p和arr的作用是一样的。注:关于指针运算可以查看复合类型-指针

怎么理解?如下图所示:
pointer_array

std::string

字符串字面值和string是不同的类型,字符串字面值是为了和C语言兼容,它不是标准库中string对象的内容。

字符串字面值常量

字符串字面值常量是用一对双引号包围一串字符。如"hello", "hi\n", ""等,'a'是字面值字符常量。
程序在使用字符串常量时,编译器会将字符串常量存放在数据区的常量区。当一个字符串常量出现在在一个表达式中,表达式使用的值是字符串常量在内存中的地址,而不是这些字符串常量本身。可以把字符串赋值给“指向字符的指针”,即让指针指向字符串常量在内存中的地址。但是不能把字符串常量赋值给一个字符数组,即不能把字符串常量的地址赋值给字符数组。比如

1
char *message1 = "Hello world!";

这个代码是将字符串常量中第一个字符的地址传递给message。

字符数组和字面值常量的区别

1
2
char message1[] = "Hello world!;
char *message2 = "Hello world!";

第一种方式,其实是一种约定,它等于char message1[] = {'H', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd', '\0'};
而第二种方式中,"Hello world"是一个字面值常量,它在内存中只能以数组的形式存在,是一个不可修改的左值表达式。而message2实际上指向了这个字符串数组的首字符。

常见的指针数组

  1. main函数的形参char *argv[]就是一个指针数组
  2. getline的第一个参数是char **lineptr

参考文献

1.《C++ Primer第五版》
2.https://www.zhihu.com/question/307261590/answer/563448215
3.https://www.zhihu.com/question/307261590/answer/563630017
4.https://stackoverflow.com/questions/10004511/why-are-string-literals-l-value-while-all-other-literals-are-r-value