c_primer_plus_CH11

自言自语

1. 表示字符串和字符串I/O

字符串是C语言最有用、最重要的数据类型之一。
字符串是以空字符\0结尾的char类型数组。

1.1. 在程序中定义字符串

  1. 字符串字面量:用双引号括起来的内容称为字符串字面量,也叫字符串常量
    双引号中的字符和编译器自动加入末尾的\0字符,都作为字符串存储在内存中。
  2. 从ANSI C标准起,如果字符串字面量之间没有间隔,或者用空白字符串分隔,C将其视为串联起来的字符串字面量。
  3. 字符串字面量属于静态存储类别,若在函数中使用字符串,该字符串只会被存储一次,用双引号括起来的内容称为指向该字符串存储位置的指针。
printf("%s, %p, %c\n", "Hello", "OK", *"fine");
//输出:Hello,0x7ffe0f43, f

1.2. 字符串数组初始化

  1. 定义字符串数组时,必须让编译器知道多少空间。比如使用足够空间的数组存储字符串。
const char str[14] = "Hello OKfine.";
//上面的形式比下面的标准数组初始化方便的多
const char str[14] = {'H', 'e', 'l', 'l', 'o', ' ', 'O', 'K', 'f', 'i', 'n', 'e', '.', '\0'};

注意:最后的空字符。若没有这个空字符,就不是一个字符串,而是一个字符数组。
在指定数组大小时,要确保数组大小的元素个数至少比字符串长度多 1(容纳空字符)
所有未被初始化的元素都被初始化未0(这里的0 指的是char类型的空字符,不是数字0)。

下面是使用指针表示法和数组表示法创建字符串:

const char *pstr = "Hello OKfine.";
//这两种形式的声明几乎相同。
const char str[] = "Hello OKfine.";

1.3. 数组和指针

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

  1. 上面的示例来说:数组形式str[]在计算机内的分配为一个含有14个元素的数组(每个元素对应一个字符,还加末尾的空字符\0)。程序在开始运行时才为数组分配内存。此时才将字符串拷贝到数组中。

    注意:此时字符串有两个副本。一个是在静态存储区中的字符串字面量。另一个是存储在str数组中的字符串.

  2. str是一个地址常量,不能更改str,如果改变了str则就改变了数组的存储位置。

    可以进行类似str + 1的操作,标识数组的下一个元素。但是不能进行str++操作。递增运算符只能存在于变量名前(只能用于可修改的左值),不能用于常量。

  3. 初始化数组把静态存储区的字符串拷贝到数组中,初始化指针只需要把字符串的地址拷贝给指针。

1.4. 数组和指针的区别

char ht[] = "Nice to meet u.";
const char *pt = "How are you?";

两者的主要区别:
数组名ht是常量,指针名pt是变量。

  1. 两者都可以使用数组表示法
for (int i = 0; i < 6; i++)
	putchar(ht[i]);
putchar('\n');
for (int j  = 0; j < 6; j++)
	putchar(pt[j]);
putchar('\n');

//输出:
//  Nice t
//  How ar
  1. 两者都能进行指针加法操作
for (int i = 0; i < 6; i++)
	putchar(*(ht + i));
putchar('\n');
for (int j  = 0; j < 6; j++)
	putchar(*(pt + j));
putchar('\n');

//输出:
//  Nice t
//  How ar
  1. 只有指针表示法可以进行递增操作
while(*pt != '\0')
	putchar(*(pt++));
//输出:How are you?

可以将pt = ht;是的指针pt指向数组的首元素。
但是不能将ht = pt;,这类似x = 3; 3 = x;在C中是非法的。

注意:pt = ht;不会导致pt指向的字符串消失,这样做只是改变了存储在pt中的地址。除非已经保存了"How are you?"的地址,否则当pt指向别处时,就无法访问该字符串。

数组的元素是变量,数组名是常量。
ht[1] = 'O';或者*(ht + 1) = 'O';

推荐使用:const char * pt = "Hi, OKfine.";

1.5. 字符串数组

  1. 指向字符串的指针数组
  2. char 类型数组的数组
#define LIM 3
#define SIZE 40
const char * mytalents[LIM] = 
{
	"Adding numbers swiftly",
	"Stashing data",
	"Understanding the C language"
}

char yourtalents[LIM][SIZE] = 
{
	"Walking in a straight line",
	"Sleeping",
	"Reading email"
}

区别:

  1. mytalents数组是一个内含3个指针的数组,在我的linux系统中占用24个字节。其中的指针指向初始化时所用的字符串字面量的位置,这些字符串被存储在静态存储区。而yourtalents数组是一个内含3个数组的数组,每个数组内含有40个char类型的值,共占用120字节。其中的数组则存储着字符串字面量的副本,所以每个字符串被存储了两次。

  2. 由此可见字符串数组分配内存的使用率较低。yourtalents中的每个元素的大小必须相同,而且必须是能存储最大字符串的大小。

  3. 综上所述,如果用数组表示一系列待显示的字符串,请使用指针数组,效率高。但是mytalents中的指针指向的字符串字面量不能被修改,而yourtalents中的值可以被修改。如果要改变字符串或为字符串输入预留空间,不要使用指向字符串字面量的指针。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值