C++指针解读(6)-- 指针和字符串

1、字符串的基本概念

(1)字符串的存储

字符串是存放在字符数组中的。比如字符串“hello”,在内存中是这么存放的:

这里要注意,在字符串的最后会加上一个'\0',也被称为NUL字符,表示字符串的结束位。比如定义char str[] = "hello",则sizeof(str)的长度是6,不是5。

(2)字符串的访问

既然字符串是字符按数组的方式存储的,我们可以用访问一维数组的方式来访问字符串。

char str[] = "hello";
printf(" %c\n", str[1]);

char* ch = &str[1];
printf(" %c\n", *ch);

(3)字符串常量池

用char数组str[]的方式定义字符串,我们也可以用下面的方式定义一个字符串:

char *str = "hello";

这里的str其实是一个char*型的指针变量,它指向字符串"hello"的首地址。

这种方式定义字符串时,"hello"是字符串常量,这个常量就放在字符串常量池中。

我们可以用代码来验证下:

const char* pstr1 = "hello";
const char* pstr2 = "hello";
printf(" p1 = %p, p2 = %p\n", pstr1, pstr2);

运行后发现pstr1, pstr2这2个地址是相同的,且每次运行地址都一样。这说明这个字符串常量是编译时就确定好的。

(4)sizeof()和strlen()

sizeof是C语言中的一个单目运算符,用来计算数据类型所占空间的大小,单位为字节;而strlen是一个函数,用来计算字符串长度(不包括字符串结束位NUL)。

char str1[] = "hello";
char str2[10] = "hello";
printf(" sizeof(str1) = %d, strlen(str1) = %d\n", sizeof(str1), strlen(str1));
printf(" sizeof(str2) = %d, strlen(str2) = %d\n", sizeof(str2), strlen(str2));

2、定义字符串的几种方式

(1)char str[] = {'h', 'e', 'l', 'l', 'o', '\0'};

定义了一个字符数组,长度为6,数组里的元素分布如下:{'h', 'e', 'l', 'l', 'o', '\0'}。

假如末尾没有NUL字符:char str[] = {'h', 'e', 'l', 'l', 'o' };

printf()输出str的值会是什么呢?sizeof()和strlen()的值分别是什么呢?

char str1[] = { 'h', 'e', 'l', 'l', 'o' };
printf(" %s\n", str1);
printf(" sizeof(str1) = %d, strlen(str1) = %d\n", sizeof(str1), strlen(str1));

这时,输出的str1是hello+一些乱码;sizeof(str1)是5,而strlen(str1)的值是个变数,每次的输出不一定相同。

因为字符串是以NUL作为字符串结束位的,现在缺少这个结束位,程序就没有办法做出正确的处理了。

(2)char str[] = "hello";

定义了一个字符数组,长度为6,系统会在末尾自动加上字位结束符NUL。

(3)char *pstr = "hello";

定义了一个字符指针变量,指向常量池中的字符常量"hello"。

4、字符指针变量和字符数组的比较

char *str1定义的是一个字符指针变量;char str2[10]定义的是一个字符数组,数组名代表数组元素首地址。

这是两个不同的概念,主要有以下区别:

(1)字符指针变量存放的是地址,指向字符串的第一个元素;字符数组就是一个存放字符的数组,一个元素就是一个字符。

(2)字符指针变量的值是可以改变的,但字符数组名的值不能改变(它只代表数组的首地址)。

const char *str1 = "hello";
printf(" %c\n", *str1);

str1++; //可以更改
printf(" %c\n", *str1);
    
char str2[10] = "hello";
str2++; //报错

(3)字符指针指向的字符串的内容不能被更改,但字符数组中各元素的值可以被更改。

const char *str1 = "hello";
str1[2] = 'a'; //报错

char str2[10] = "hello";
str2[2] = 'a'; //可以

(4)我们可以用str2[1], *(str2 + 1)这样的方式访问数组元素;对于字符指针变量,同样也可以用str1[1], *(str1 + 1)这样的方式访问。

const char *str1 = "hello";
printf(" %c, %c \n", str1[1], *(str1 + 1));

char str2[10] = "hello";
printf(" %c, %c \n", str2[1], *(str2 + 1));

(5)初始化的含义

char *str1 = "hello";

等价于:

char *str1;
str1 = "hello"; //把字符串的首地址给str

但字符数组的初始化:

char str2[10] = "hello";

不等价于:

char str2[10];
str2 = "hello"; //报错

其实这里的str1是个char *类型的指针变量,即字符指针变量,把字符数组的首地址赋给这个指针变量是没问题的。

而str2是数组的名字,代表字符数组首元素的地址,我们可以给这个地址赋值,但不能让地址去指向另外一个地址。

char str1[10];
*str1 = 'h'; //可以给地址赋值
strcpy(str1, "hello"); //可以直接内存拷贝

5、字符指针作函数参数

前面我们知道可以用两种方式来定义字符串,一种是字符数组,另一种是字符串指针变量。当函数的形参是字符串时,我们可以传字符数组的首地址,也可以传字符串指针变量。

(1)传字符数组的首地址

void print_str(char str[]) {
    int i = 0;
    while (str[i] != '\0') {
        printf("%c", str[i]);
        i++;
    }
}

int main()
{
    const char *str1 = "hello";
    print_str((char*)str1);

    char str2[10] = "hello";
    print_str(str2);

    return 0;
}

(2)传字符串指针变量

void print_str(char* str) {
    int i = 0;
    while (str[i] != '\0') {
        printf("%c", str[i]);
        i++;
    }
}

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值