鸦片战争史读后感:字符串文字量
来源:百度文库 编辑:偶看新闻 时间:2024/04/27 01:55:32
站在巨人肩上的思考[连载] (8)
5.2 数组
5.2.2 字符串文字量
类似”this is astring.”这样一个字符串文字量,它是一个常量。正如代码中一个显式的数字0xff08一样,其值不可以被更改。如想修改,可以通过复制给一个变量来实现:
int a = 0xff08;
a = 0xff18;
对于字符串文字量则有一点要注意:
char* cp = “this is a string”; //危险!赋值给一个普通字符指针;
cp[4] = ‘e’; //未定义行为!不能给常量赋值;
char p[] = “this is a string”; //可以;
p[4] = ‘e’; //正确执行;
可以看出,用char*来引用字符串文字量是一个十分危险的地方。在上例中cp[4]=’e’;可以通过编译,但是在执行期间产生了一个SegmentationFault。也就是说编译器并不能帮助程序员发现这类错误。
我个人是这样认为的:字符串文字量是一中很底层的数据,编译器把他放进汇编语言中的数据段;普通的char*指针也是一种很底层的指针,他可以指向内存空间中的任何地址;char* cp = “this is a string”;仅仅在栈空间生成一个指针,然后把他指向位于数据段的”thisis a string”,初始化并不会导致错误。但是利用cp[4]更改数据段中的数据内容将会导致段错误,数据段是只读的。而利用char p[]形式的时候,意味着将在栈空间中生成一个字符数组,然后用”thisis a string”来进行初始化,而后p指向这个栈空间中字符数组的首地址。此时p[4]=’e’;修改的是栈空间中的值,而不是数据段中的值。
但是p是什么类型呢?是char*么?他的大小是多少?是1么?为了使指针和数组首地址之间的区别更具普遍意义,我们用int类型来测试一下:
char p[] = "hello";
char* ptr = p;
cout << sizeof(p) << ":" << sizeof(*p) << endl;
cout << p << ":" << *p << endl;
cout << sizeof(ptr) << ":" << sizeof(*ptr) << endl;
cout << ptr << ":" << *ptr << endl;
这段代码在我的电脑上的输出是:
[/home/gavin/test]# ./test
6:1
hello:h
4:1
hello:h
ptr是真正的char*类型,其sizeof是4,但是p的sizeof却是6,也就是”hello”加一个‘\0’的长度。除此之外,ptr和p表现都一样。但我们最好认为p是字符数组类型,而ptr才是字符指针类型,因为他们的行为上存在差异。很多教师、教材都说:“数组名就是指向数组首地址的指针。”这其实并不完全正确。
再仔细看看,我们cout< 和cout< int arr[4] = {0}; int* pa = arr; cout << sizeof(arr) << ":" << sizeof(*arr) << endl; cout << arr << ":" << *arr << endl; cout << sizeof(pa) << ":" << sizeof(*pa) << endl; cout << pa << ":" << *pa << endl;
在我的电脑上输出为:
[/home/gavin/test]# ./test
16:4
0xbfc26e5c:0
4:4
0xbfc26e5c:0
sizeof的输出刚才已经说过。这里可以看出,int数组名和char数组名的行为也不一样。事实上,cha数组名与标准类型数组名的行为都不一样。这也就是为什么C风格字符串为许多人诟病的地方。
C++在这方面提供了很好的改进:用一种更上层的类型string来代替C风格字符串。并强烈建议程序员在程序中尽量使用string来代替char *。这里是你需要做出选择的地方:
string str1("1");
string str2("1234567");
string str3("1234567890123456789012345678901234567890");
/*
char str1[] = "1";
char str2[] = "1234567";
char str3[] = "1234567890123456789012345678901234567890";
*/
cout << sizeof(str1) << endl;
cout << sizeof(str2) << endl;
cout << sizeof(str3) << endl;
当利用C风格字符串的输出为:
[/home/gavin/test]# ./test
2
8
41
[/home/gavin/test]# ls -l
-rwxrwxr-x 1 863 863 6559 Dec 3 14:29 test
-rw-rw-r-- 1 863 863 391 Dec 3 14:29 test.cpp
而当使用string时:
[/home/gavin/test]# ./test
4
4
4
[/home/gavin/test]# ls -l
-rwxrwxr-x 1 863 863 7578 Dec 3 14:30 test
-rw-rw-r-- 1 863 863 390 Dec 3 14:30 test.cpp
我们也许可以得到如下结论:sting比char[]需要更少的运行时内存空间,但是char[]却比string占用更少的磁盘空间。你可以自己选择向左还是向右走。不过相比string的易用性、安全性、以及诸多的成员函数带来的实用功能来说,我个人并不认为char[]节省的磁盘空间是很突出的优点。