这篇文章上次修改于 525 天前,可能其部分内容已经发生变化,如有疑问可询问作者。

在实际使用中发现对字符串的运用是一个容易混乱的地方,尤其是使用指针指向一个字符串数组的时候。下面做一些简单分析。

一个简单的测试:

    const char* test1 = "abc";
    const string test2 = "abc";

    cout << test1 << endl;
    cout << *test1 << endl;
    cout << test2 << endl;
    cout << sizeof (test1) << endl;
    cout << sizeof (test2) << endl;

输出如下:

abc
a
abc
8
24

以前我的教程里提到过,字符串就相当于一个字符数组。指针会指向它的首个字符地址。test1 指针理论上存储着字符串的首地址。

但我们可以看到直接输出 test1 会得到实际字符串内容,而不是首个字符地址。输出 *test 会得到正常的首字符内容。

字符串指针使用 sizeof 得到这个指针所占用内存大小,而不是字符串内容的大小。

同时我们可以发现,一个字符指针可以直接指向一个字符串,而不需要先定义一个字符串变量然后建立指针指向这个变量。这是因为一个字符串可以看做一个字符数组,同时它也是一个整体,字符指针可以直接定义指向它。

下面测试 int 型数组:

    const int test3[] = {1, 3 ,5};
    const int* test4 = test3;

    cout << test3 << endl;
    cout << test4 << endl;
    cout << test4[0] << endl;
    cout << *test4 << endl;
    cout << sizeof(test4) << endl;
    cout << sizeof(test4[0]) << endl;

输出结果:

0x7ffee8cbaa58
0x7ffee8cbaa58
1
1
8
4

可以看到直接输出数组名称或指针名称得到的是数组所在地址。*testtest[0] 会得到数组第一位内容。

test4 是一个指针,所以 sizeof 得到的是这个指针做占用的内存空间而不是数组本身占用空间。无法通过 sizeof 计算出数组个数。

以上实验,我们先建立了一个 int 型数组变量,然后建立 int 型指针指向这个变量,如果直接在一行中建立一个指针指向一个数组会报错,这就和上面测试的字符指针不一样了。因为其他类型的数组不同于字符串,它的每个元素是独立的个体,所以无法使用一个指针直接指向他们全部。

下面做最后一个测试:

const char* test5[] = {
    "abc",
    "def",
    "ohg",
    "asdf"
};

const string test6[] = {
    "abc",
    "def",
    "ohg",
    "asdf"
};

int x = sizeof (test5)/sizeof(test5[0]);
cout << test5 << endl;
cout << *test5 << endl;
cout << test5[0] << endl;
cout << *test5[0] << endl;
cout << x << endl;
cout << sizeof(test5) << endl;
cout << sizeof(test5[0]) << endl;

cout << "*************\n";

x = sizeof (test6)/sizeof(test6[0]);
cout << test6 << endl;
cout << *test6 << endl;
cout << test6[0] << endl;
cout << x << endl;
cout << sizeof(test6) << endl;
cout << sizeof(test6[0]) << endl;

输出结果如下:

0x7ffee596ea40
abc
abc
a
4
32
8
*************
0x7ffee596e9e0
abc
abc
4
96
24

由于字符串本身就是一个字符数组,所以一个字符串数组相当于一个二维的数组。定义字符串数组的指针,就是数组中每个字符串对应的指针的集合。所以这个数组指针本身不是字符串类型的,而它的每个指针元素都是字符串指针类型的。

可以看到类似于第一组测试,非字符串的指针直接输出指针名称,所以 test5 得到字符串数组的地址。

*test5test5[0] 都表示指针数组第一个元素,也就是字符串类型的指针,根据第一组实验可以知道使用字符串指针名称输出本身字符串而不是地址,所以输出此指针可以直接得到字符串内容。

*test5[0] 就是字符串指针的首字符地址内容,也就是得到第一个字符串第一个字符的内容。

test5 指针数组使用 sizeof 得到的是这个指针数组总共占用的内存大小,也就是每个指针大小的总和。除以单个指针大小就可以得到这个数组指针的个数,也就是对应指向的数组的元素个数。

test6 字符串数组使用 sizeof 得到的是这个字符串数组所有元素的占用内存大小,除以单个字符串大小就可以得到这个数组的元素个数。

我们可以看到 test5 和 test6 使用 sizeof 都可以得到数组的元素个数,但他们的原理是完全不同的,一个是使用指针的内存大小,一个是使用数组本身的内存大小。

总结:
字符串的指针名称可以直接输出字符串内容而不是地址。其他指针类型指向的数据,如字符,数字,字符串数组,number 型数组等,指针名输出的都是数据地址。

指针使用 sizeof 得到的是指针所占用的内存大小。可以使用 sizeof(*Pointer) 得到数据本身大小。

字符串数组的指针使用 sizeof 得到指针数组的总大小,可以用来间接计算数组元素个数。