文章目录
- 前言
- 一、字符串简介
- 二、字符串定义形式
- 1、以字符数组形式定义
- 2、以char*形式定义
- 3、以const char*形式定义
- 4、以string形式
- 三、地址输出
- 四、sizeof和strlen比较
- references
前言
本文用于记录C/C++中字符串的相关知识
一、字符串简介
字符型变量(char)用于存储一个单一字符,其中每个字符变量都会占用 1 个字节。在给字符型变量赋值时,需要用一对英文半角格式的单引号(’ ‘)把字符括起来。字符变量实际上并不是把该字符本身放到变量的内存单元中去,而是将该字符对应的 ASCII 编码放到变量的存储单元中。char的本质就是一个1字节大小的整型。
**字符串是内存中一段连续的char空间,以’\0’(数字0)结尾。**字符串常量是由双引号括起来的字符序列,如“china”、“C program”,“$12.5”等都是合法的字符串常量。
字符串常量与字符常量的不同:
每个字符串的结尾,编译器会自动的添加一个结束标志位’\0’,即 “a” 包含两个字符’a’和’\0’。
二、字符串定义形式
1、以字符数组形式定义
字符串一定是一个char型数组,但char型数组未必是字符串
char str1[] = {'h', 'e', 'l', 'l', 'o'}; printf("%s\n", str1); // 普通字符数组,一般输出为乱码 char str2[] = {'h', 'e', 'l', 'l', 'o', 0}; char str3[] = {'h', 'e', 'l', 'l', 'o', '\0'}; printf("%s\n", str2); // hello printf("%s\n", str3); // hello
测试数组的大小和字符串的长度
char str4[] = "hello world";char str5[100] = "hello world";char str6[] = {'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', 0};char str7[] = {'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', '\0'};printf("str4=%d\n", strlen(str4)); //11printf("str5=%d\n", strlen(str5)); //11printf("str6=%d\n", strlen(str6)); //11printf("str7=%d\n", strlen(str7)); //11printf("str8=%d\n", strlen(str8)); //11printf("str4=%d\n", sizeof(str4)); //12printf("str5=%d\n", sizeof(str5)); //100printf("str6=%d\n", sizeof(str6)); //12printf("str7=%d\n", sizeof(str7)); //12printf("str8=%d\n", sizeof(str8)); //100
首先需要注意的是sizeof是关键字不是函数,不需要包含任何头文件,而且strlen和sizeof返回类型是size_t,格式化输出%d会产生如下警告:
言归正传,从输出结果可以看出,strlen函数不会计算最后的结束标志符’\0’,无论是人为添加的(如str6\str7)或编译器添加的(如str4),str5、str8是一个长度为100的字符型数组,其未初始化位置默认初始化为0。
注意:定义字符数组一定要进行初始化!
看下面这个例子:
未初始化
void test01(){ char test[40]; for(int i=0; i<26; ++i) { test[i] = 'A' + i; } for(int i=0; i<26; ++i) { printf("%c ", test[i]); }// A B C D E F G H I J K L M N O P Q R S T U V W X Y Z printf("\n"); printf("%d\n", sizeof(test)); // 40 printf("%d\n", strlen(test)); // 29}
初始化
void test02(){ char test[40] = {0}; for(int i=0; i<26; ++i) { test[i] = 'A' + i; } for(int i=0; i<26; ++i) { printf("%c ", test[i]); }// A B C D E F G H I J K L M N O P Q R S T U V W X Y Z printf("\n"); printf("%d\n", sizeof(test)); // 40 printf("%d\n", strlen(test)); // 26}
从输出结果可以看出,未初始化的字符数组strlen后的结果不对,这是因为当我们对test字符串进行时,申请到一块内存,此时这块内存中可能储存有值,导致使用strlen计算test字符串时找不到字符串结束标志 ’\0‘(strlen不计算\0的结果),而会在test申请的那片内存后面一直找下去,找到 ’\0‘ 后输出,计算的结果,此时输出的结果肯定错误的结果。
2、以char*形式定义
char*本质上是一个常量指针。
char *s1 = "hello";//s1[0] = 'H'; erros1 = "world";printf("%s\n",s1); // world
char*是一个常量指针(常量的指针),即它指向的内存中的内容不能发生改变,但它可以改变自身的指向。
char s2[] = "java"; char *s3 = "python"; s3 = s2;
注意:char*形式定义字符串具有风险
char *p = "hello";
- 在栈区开辟内存放char* p。
- 在常量存储区开辟内存放”hello”。
- 将”hello”中第一个字符的内存地址赋值给p。
其中,”hello”是不允许修改的。当你试图去修改内存中的常量区,肯定会报错!
3、以const char*形式定义
const char* 是一个常量指针,表示指针的指向可以修改,指针的值无法修改。
const char* s1 = "hello";printf("%s\n", s1);char s2[] = "world";s2[0] = 'W';s1 = s2;printf("%s\n", s1);//s1[0] = 'w'; error 表达式必须是可修改的左值
相较于char * 形式,const char * 的形式更加直接明了,建议使用这种形式。
4、以string形式
区别 | string | char* |
---|---|---|
本质 | STL中的一个容器,封装了char * | 常量指针 |
内存管理 | 由系统进行管理,无需手动处理 | 堆/栈,如果是堆需要手动进行释放 |
string 和 const char*互转
//string转const char*#include string s = "sss";const char* c = s.c_str(); //const char*转stringconst char* c = "ppp";string s = c;
string 和 char *互转
//string转char*#include string str = "string";//法一char* chr = const_cast<char*>(str.c_str());//法二char *cstr = &str[0]; //char*转stringchar* c = "ppp";string s = c;
三、地址输出
printf
char s1[] = "hello";char *s2 = "hello";const char *s3 = "hello";char s4[10] = {'h', 'e', 'l', 'l', 'o'};printf("%p\n", s1); // 0x16d3ab1a0printf("%p\n", s2); // 0x102a57fa2printf("%p\n", s3); // 0x102a57fa2printf("%p\n", s4); // 0x16d3ab1a8
cout
char s1[] = "hello";char *s2 = "hello";const char *s3 = "hello";char s4[10] = {'h', 'e', 'l', 'l', 'o'};string s5 = "hello";cout << &s1 << endl; //0x16b08b1b0cout << &s2 << endl; //0x16b08b1a8cout << &s3 << endl; //0x16b08b1a0cout << &s4 << endl; //0x16b08b1b8cout << &s5 << endl; //0x16b1ff188
四、sizeof和strlen比较
sizeof | strlen | |
---|---|---|
性质 | 运算符 | 函数 |
头文件 | 无 | string.h |
功能 | 以字节为单位计算操作数占用的内存大小 | 计算字符串的长度 (strlen函数遇到\0就会停止下来,返回\0前出现的字符个数,不包括\0) |
时间 | 编译时 | 运行时 |
返回值 | size_t | size_t |
参数 | 基本类型/自定义类型 | const char*\char*\char[] |
references
C、C++ 对于char*和char[]的理解
char * 和const char *的区别