C语言是面向过程的,所以它并没有所谓封装好的功能强大的string。但是麻雀虽小五脏俱全。在C中,我们一般用
const char* 类型来定义一个字面型字符串。
首先我们了解下C中的基本指针。指针是存储变量地址的变量。而我们主要来区别下数组指针和普通指针。
看一段代码:
char c = ‘d‘; char* ptr_c = &c; printf(ptr_c);
这段代码是能通过编译的,然而执行的时候会出现不可预期的错误。虽然printf接受的是一个const char* 类型的参数。但是显然不是所有的char* 类型的参数都是它所预期能接受的。
上述的ptr_c是一个指向单个字符char的地址。如果对其进行+ - 运算,那么获得的地址将是不可预期的。
我们修改一下:
char cstring[3]; ptr_c = cstring; //1 *(ptr_c++) = ‘a‘; //2 *(ptr_c++) = ‘b‘; *(ptr_c) = ‘\0‘; //3 printf("%c ",*cstring); //4 printf(cstring); //5
上述代码虽然简单,但是句句暗藏玄机。
1.cstring是数组的名字,但是创建数组的时候,他会自动创建一个指针。这个指针可以赋值给一个char类型的指针。是一个右值(所以也可以看成是头指针)。
这行代码等价于:
ptr_c = &cstring[0];
此外,这个数组的所有元素的地址是按照一定的规则排列的,所以指针的+ -运算可以得到对应元素的地址。比如,第一个元素的地址+2就是第三个元素的地址,但计算的时候一定要注意不要越过数组的界限。
2.*(ptr_c++) 的操作步骤是先解引用,然后将指针+1。对于理解上很容易误解,很容易看成是先将指针+1再解引用。这是不对的。要注意。
3.一定注意:c语言的字符串约束是末尾字符是\0,也就是说满足末尾字符是\0的的字符数组就可以当作c字符串来使用。
4.同1,cstring解引用后会获得第1个元素的值。
5.c语言中所有const char* 类型的参数或者返回值,都可以当作是字符串。他们满足的约束也是尾字符是\0。所以这次我们传一个真正的字符串进去,printf(const char *)方法才能正确执行。
了解了这么多,相比大家早就对实现strcpy方法跃跃欲试。这是c最经典的一道面试题,同时也囊括了刚才介绍的不少知识点。
char* strcpy(char* dest, const char* src) { assert(dest != NULL && src != NULL); char* ret = dest; while(*(dest++) = *(src++) != ‘\0‘); return ret; }
最后说下,C中的字符串字面值常量,编译器将视他为const char*类型。所以可以直接赋值。
此外,const char* 被赋值后,这个值就不能再变化,我曾经试着作死但是明显失败了
const char* ntr = "ninij";
char* str = const_cast<char*> (ntr);
*str = ‘a‘;
printf(ntr);//严重报错,一旦str被赋值,原ntr的结构被破坏!!慎重!!!
对此我们需要理解下const的作用:
常量指针,表述为“是常量的指针”,它首先应该是一个指针。
指针常量,表述为“是指针的常量”,它首先应该是一个常量。
常量指针 const char *p; p指向的内容不可变
指针常量 char* const p; p指向的地址不可变