字符串可以分配在内存的不同区域,通常用指针来支持字符串操作,指针支持动态分配字符串和将字符串作为参数传递给函数。知道字符串的位置对理解程序的工作原理以及用指针访问字符串有帮助。字符串的位置决定它能存多久,以及程序的哪些部分可以访问它。比如说,分配在全局内存的额字符串会一直存在,可以被多个函数访问。静态局部字符串也一直存在,不过只有定义他们的函数才能访问,分配在堆上的内存在释放之前会一直存在,也可以被多个函数访问。
字符串通常以字符指针的形式传递给函数和从函数返回,可以用字符指针传递给字符串,也可以用字符常量的指针传递字符串,后者可以避免字符串被函数修改。
1.字符串初始化
字符串是以ASCII字符'\0'结尾的字符序列,通常存储在数组或者从堆上分配的内存中声明字符串方式有三种:字面量、字符数组及字符指针。
字面量是用双引号括起来的字符序列,常用来初始化字符串数组操作。
char* string = "hello";
char str[] = "this is a string";
初始化char指针
常使用malloc和strcpy函数来分配内存并将字面量复制到字符串。在使用malloc分配字符串长度时候,一定要记得算上终止符'\0', 同时不要用sizeof操作符,而是用strlen函数确定字符串长度,sizeof返回数组和指针的长度,而不是字符串的长度。
char* header = (char*)malloc(strlen("media player") + 1);
strcpy(header, "media player");
2.传递字符串
传递字符串很简单,用char*指针类型作为函数形参即可,如果不允许函数内部改变字符串,可以用const char*传递参数。
size_t stringLen(char* string)
{
size_t length = 0;
while(*string++)
{
length++;
}
return length;
}
字符串常量指针形式传递字符串指针,可以防止传递的字符串被修改,如下面例子,试图修改原字符串,就会产生一个编译错误
size_t stringLen(char* string)
{
...
*string = 'A';
...
}
传递需要初始化的字符串
有些情况下让函数返回一个由该函数初始化的字符串,需要传输一个缓冲区,通常需要传递缓冲区的地址和长度,调用者负责释放缓冲区,函数通常返回缓冲区的指针。这种方法把分配和释放缓冲区的责任都交给了调用者。
char* format(char* buffer,size_t size, const char* name)
{
snprintf(buffer,size, "item:%s", name);
return buffer;
}
3.返回字符串
函数返回字符串时,返回的实际是字符串的地址。实际一般可以返回字符串字面量和动态分配的内存,不能返回局部字符串数组的地址。
char * returnAliteral(int code)
{
switch(code) {
case 100:
return "bosoton";
case 200:
return "denver";
break:
return NULL;
}
返回动态分配内存的地址:
char * stringToLower(const char* string)
{
char* tmp = (char*) malloc(strlen(string) + 1);
char* start = tmp;
while(*string != 0)
{
*tmp++ = tolower(*string++);
}
*tmp = 0;
return start;
}
不能返回局部数组的字符串地址
char * blanks(int number)
{
char spaces[MAX_LENGTH];
int i;
for(i = 0; i< number; i++)
{
spaces[i] = ' ';
}
spaces[number] = '\0';
return spaces;
}
上面的函数返回数组的地址,每次调用函数后,地址所在的内存区域都会被覆盖,解引用指针后,该内存地址的内容已经改变。
总结:
讲解了字符串操作和指针的使用,字符串的结构和在内存中的位置会影响其使用。