c primer plus 第11章字符串和字符串函数(11.1)

(1)什么是字符串

以空字符(\0)结尾的char类型数组

11.1.1如何定义字符串

1.字符串字面量(字符串常量)

双引号中的字符和编译器自动加入末尾\0的字符,都作为字符串存储在内存中。属于静态存储类别,只会被存储一次,在整个程序的生命期内存在,即函数可被多次调用。(双引号括起来的内容被视为指向该字符串存储位置的指针)

从ansi c标准起,如果字符串字面量之间没有间隔或用空白字符间隔,c会将其视为串联起来的字符串字面量。

ex:char a[50]="hello,and""  how are"    "  you"

"  today!";等价于

char a[50]="hello,and  how are  you  today!";

下面代码:

printf("%s %p %c\n","we","are",*"space farers");

output:

we  0x100000f61,s

tips:*"space farers"表示该字符串所指向地址上的存储的值,应该是字符串"space farers"的首字符。因为上面红色括号里面的道理

2字符数组和初始化

定义字符串数组时,必须让编译器知道需要多少空间。

一种方法用足够空间的数组存储字符串。

const char m[20]="hello world!";const表明不会更改这个字符串

这种形式的初始化比标准的数组初始化形式简单的多:

const char m[20]={'h','e','l','l','o','w','o','r','l','d','!','\0'};

注意:最后的空字符。没有这个空字符,就不是一个字符串而是一个字符数组

下面这个知识点:在指定数组大小时,要确保数组的元素的个数至少比字符串长度多1(为容纳空字符)。所有未被使用的元素都自动化为0(这里的0(即\0)指的是char形式的空字符,不是数字字符0)

第2种方法:让编译器确定数组的大小很方便,省略数字初始化声明中的大小,编译器会自动计算数组大小

const char m[ ]="hello world!";

让编译器计算数组的大小只能用在初始化数组时。如果创建一个稍后再填充的数组,就必须在声明时指定大小。声明数组时,数组大小必须是可求值的整数。在c99新增变长数组之前,数组的大小必须为整型常量,包括整形常量组成的表达式。

第3种方法:

const char *p="hello world!";

解释:第2种和第3种方法,声明的m,p都是该字符串的地址,在这2种情况下,带双引号的字符串本身决定了预留给字符串的存储空间。。尽管如此这2种形式不完全相同,,下面3数组和指针就是解释有什么不同

3数组和指针(难点)

数组形式和指针形式有何不同?

原理:

字符串存储在静态存储区,程序运行时才为数组分配内存,此时才将字符串拷贝到数组中。(此时字符串有2个副本,一个在静态内存中的字符串字面量,另一个存储在m数组中字符串)数组,数组名为常量。

指针形式p也使得编译器为字符串在静态存储区预留13(12+1)个元素的空间。另外,一旦开始执行程序,它为指针变量p留出一个存储位置,并把字符串的地址存储在指针变量中。该变量最初指向该字符串的首字符,但它的值可以改变(数组名是常量,指针名为变量)。

修改内容的不同:

​​​​​字符串字面量被视为const数据。由于p指向这个const数据,所以把p声明为const数据的指针。这意味这不能用p改变它指向的数据,但是仍然可以改变p的值。如果把一个字符串字面量拷贝给一个数组,就可以随意改变数据,除非把数组声明为const。(数组元素是变量,数组名常量)

总结:初始化数组把静态存储区的字符串copy到数组,但初始化指针只把字符串的地址copy给指针。

引申:静态存储和动态存储?

4数组和指针区别

char heart[]="i love china!";

char *head="i love china!";

(1)访问方式都可用数组法和指针加法,但是指针可以用递增操作

head=heart;不会导致head指向的字符串消失,只是改变存储在head中的地址。除非已经保存了

"i love china!"的地址,否则head指向别处,就无法再访问该字符串。

(2)用指针出现的问题

char *word="frame";

word[1]='l';是否允许

编译器可能允许这样做,但对当前的c标准语言,这样的行为未定义。

因为:编译器可把多次使用的相同字面量存储在一处或多处,这完全取决于编译器

解决办法:

初始化时,字符串字面量使用const限定:const char *word="frame";//推荐用法

但是,非const数组初始化为字符串字面量却不会导致类似的问题,这是由原理:

字符串存储在静态存储区,程序运行时才为数组分配内存,此时才将字符串拷贝到数组中。(此时字符串有2个副本,一个在静态内存中的字符串字面量,另一个存储在m数组中字符串)数组,数组名为常量。数组得到时原始数组字符串的副本

总结:如果打算修改字符串,就不要用指针指向字符串字面量(因为第3部分数组和指针)的原理

5字符串数组

#include <iostream>
using namespace std;
#define LIM 5
#define SLEN 40
int main()
{
    const char* my[LIM] = {
        "adding","multiplying","stashing","happy","rainbow"
    };
    char your[LIM][SLEN] = {
        "wlaking in a straight line","sleeping","reading","repeat","practice"
    };
    int i;
    cout << "compare talents:\n";
    for (i = 0; i < LIM; i++)
    {
        cout << my[i] << endl;
        cout << your[i] << endl;
    }
    cout << sizeof(my)<<endl;
    cout << sizeof(your) << endl;
    std::cout << "Hello World!\n";
}

对比如下代码:

#include <iostream>
using namespace std;
#define LIM 5
#define SLEN 40
int main()
{
    const char* my[LIM] = {
        "adding","multiplying","stashing"
    };
    char your[LIM][SLEN] = {
        "wlaking in a straight line","sleeping","reading"
    };
    int i;
    cout << "compare talents:\n";
    for (i = 0; i < LIM; i++)
    {
        cout << my[i] << endl;
        cout << your[i] << endl;
    }
    cout << sizeof(my)<<endl;
    cout << sizeof(your) << endl;
    std::cout << "Hello World!\n";
}

为什么没有打印sizeof?

字符串指针设为LIM=5,因为初始化只有3个字符串,指针没有完全初始化!!!指针必须初始化!我的计算机一个指针占4个字节,但是下面列出的照片一个指针占8字节,5个字符串指针就是40字节(主要是-----因为编译器)

相似之处和区别:

// 指针和字符串c primer plus 281页.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//2024-8-26

#include <iostream>
#include<stdio.h>
using namespace std;
int main()
{
    const  char* mesg = "Don't be a fool!";
    const char* copy;
    copy = mesg;
    cout << copy << endl;
    printf("mesg=%s;&mesg=%p;value=%p\n",mesg,&mesg,mesg);
    printf("copy=%s;&copy=%p;value=%p\n", copy, &copy, copy);
    std::cout << "Hello World!\n";
}

 

 因此,程序未拷贝字符串。语句copy = mesg;把mesg的值赋给copy,即让copy也指向mesg指向的字符串。这样更高效,只需知道一个地址就行了。

如果确实拷贝整个数组,可使用strcpy()或strncpy()函数。

总结:所有11.1节主要由于字符指针和字符数组的原理造成的。

数组形式和指针形式有何不同?

原理:

字符串存储在静态存储区,程序运行时才为数组分配内存,此时才将字符串拷贝到数组中。(此时字符串有2个副本,一个在静态内存中的字符串字面量,另一个存储在m数组中字符串)数组,数组名为常量。

指针形式p也使得编译器为字符串在静态存储区预留13(12+1)个元素的空间。另外,一旦开始执行程序,它为指针变量p留出一个存储位置,并把字符串的地址存储在指针变量中。该变量最初指向该字符串的首字符,但它的值可以改变(数组名是常量,指针名为变量)。

修改内容的不同:

​​​​​字符串字面量被视为const数据。由于p指向这个const数据,所以把p声明为const数据的指针。这意味这不能用p改变它指向的数据,但是仍然可以改变p的值。如果把一个字符串字面量拷贝给一个数组,就可以随意改变数据,除非把数组声明为const。(数组元素是变量,数组名常量)

总结:初始化数组把静态存储区的字符串copy到数组,但初始化指针只把字符串的地址copy给指针。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值