复制字符串是常见的操作,通常用strcpy
函数实现,其原型如下:
char* strcpy(char *s1, const char *s2);
本节会讲到基本的复制过程和常见的陷阱。假设要将一个已有的字符串复制到动态分配的缓冲区中(也可以用字符数组)。
有一类常见的应用程序会读入一系列字符串,挨个存入占据最少内存的数组。要实现这一点,可以创建一个长度足以容纳用户可能输入的最长字符串的数组,并且把字符串读入这个数组。有了读入的字符串,我们就能分配合适的内存。基本的方法是这样的:
- 用一个很长的
char
数组读入字符串 ; - 用
malloc
分配恰好容纳字符串的适量内存 ; - 用
strcpy
把字符串复制到动态分配的内存中。
下面的代码说明了这种技术。names
数组会持有每个读入的名字的指针,而count
变量则指定下一个可用的数组元素。name
数组用来持有读入的字符串,每个读入的名字都可以重复利用它,malloc
函数分配每个字符串所需的内存并将其赋给names
中下一个可用的元素。之后将名字复制到新分配的内存中:
char name[32];
char *names[30];
size_t count = 0;
printf("Enter a name: ");
scanf("%s",name);
names[count] = (char*)malloc(strlen(name)+1);
strcpy(names[count],name);
count++;
我们可以在一个循环中重复这个操作,每次迭代增加count
值。下图说明了对于读入的名字Sam,这些处理的内存布局。
两个指针可以引用同一个字符串。两个指针引用同一个地址称为别名,这个话题会在第8章讲到。尽管通常情况下这不是问题,但要知道,把一个指针赋值给另一个指针不会复制字符串,只是复制了字符串的地址。
为了说明这一点,下面声明了页眉指针的数组。我们将字符串字面量的地址赋给了索引为12的页面,接着,把pageHeaders[12]
中的指针复制到pageHeaders[13]
。现在这两个指针都指向同一个字符串字面量。这里复制的是指针而不是字符串:
char *pageHeaders[300];
pageHeaders[12] = "Amorphous Compounds";
pageHeaders[13] = pageHeaders[12];
下图解释了这些赋值操作。