攻克C语言难点:字符串常量、字符数组与指针深入原理


  • 内容包含:

▪字符

▪字符串常量

▪字符数组和字符指针

大家是否想过这些问题?字符串和单个字符有什么区别?字符串是就是一大堆字符合在一起嘛?

   

字符串怎么存储?存储在哪里?

 

下面我们来逐个讨论一下

 


▪字符

  • 字符的表示形式:在C语言中字符的表示形式有两种,一是字符的字符形式,二是字符的编码形式。

 

字符集为每一个字符分配了唯一存在的编号(编码值)。

 

在C语言中,一个字符除了可以用字符形式来表示(如字符’a’的字符形式:a) 

 

也可以用它的编码形式来表示(如字符’a’的其中一种编码形式:‘\x61’)

 

  • 转义字符的定义:用编码形式表示的字符被称为转义字符。

 

  • 转义字符的用法:转义字符以 ‘\’ 或者 ‘\x’ 开头,

 

以 ‘\’ 开头的后面跟的是八进制形式的编码值,对于转义字符来说只能用八进制或者十六进制

实例:

char k = '\61';//表示字符1
char a = '\x31';//表示字符1
char b = '\0';//表示字符0

▪字符串常量

  • 字符常量:由一对单引号构成的闭合结构中存在的单个字符,比如’a’ ‘b’ ‘c’ ‘d’。
  • 字符串常量:由多个字符常量组成且以转义字符(’\0’)结尾的一串字符。

 

另外,在C语言种字符串常量把多个字符常量括在双引号内构成闭合结构,且结尾自动添加(‘\0’)结束符。

 

  • 转义字符‘\0’:代表ascii码为0的字符,用它来表示作为字符串的结束标志。

 

 

以上说的是字符串的表现形式,那么字符串如何存储呢?

 

首先,C语言中没有专门提供字符串的数据类型,我们通常使用字符数组和字符指针来处理字符串。


▪字符数组:

 

  • 字符数组来表示字符串:先声明一个字符数组,比如char arr[80]

 

然后将字符串结束标志(‘\0’)作为字符数组的最后一个元素即可。

 

 

  • 字符数组的初始化:

 

①用字符常量的初始化列表对数组初始化

char str[7]={'a', 'b', 'c', 'd', 'e', 'f', '\0' };

 

②用字符串常量直接对数组进行初始化

char str[7]={"abcdef"};

char str[7]="abcdef";

char str[]="abcdef";

 

 

  • 字符指针:还可以用字符指针来指向一个字符串。

如果让一个指针指向字符串常量:

char *pstr= “hello world”;

此时字符指针指向字符串首地址,其反汇编代码:

00DF1865 C7 45 F8 30 7B DF 00
mov          dword ptr [pstr],offset string "hello world"(0DF7B30h)

学过汇编的读者一目了然,这里为没学过汇编的读者解释一下:

 

dword ptr [pstr],其中的dword表示两个字节

dword ptr [pstr]:表示指针pstr所在的存储单元

offset string”hello world”:字符串”hello world”的存储单元首址

mov:将右边的数据(原操作数)赋值到左边(目的操作数)。

所以可以看到字符指针指向字符串的首地址

在讲下一个问题之前,先说两个字符串指针结论:

 

①字符串的指向可以修改

②不能通过对字符串的解引用来修改字符串常量的值

不能通过对字符指针解引用来实现修改字符串存储单元里的数据。

比如下面这段代码就是错误的!

char *pstr =  "abcdefg";
*pstr = "hello";//这一行代码是错的,不能通过对字符指针解引用来修改字符串常量存储单元的内容 

这样做的结果就是报错

为什么呢?

在解释这个问题之前,先大致说一下内存结构。


▪五大内存分区

 

内存主要分为五个区域:堆、栈、自由存储区、全局/静态存储区和常量存储区。

 

这里重点说一下常量存储区

 

常量存储区:这是一块比较特殊的存储区,它们里面存放的是常量

 

原则上不允许修改其中的数据存储单元的内容(但可以通过非正常手段修改)

 

所以其本质原因是:字符串常量存储在常量存储区

 

而常量存储区的数据存储单元原则上不可修改。

 

所以不能通过对字符指针解引用来实现修改字符串存储单元里的数据。

 

 

但是可以修改指针的值(指向),即指针里面存储的字符串地址是可以修改的。

 

例子:改变字符指针的指向

 

char arr[]="abcdefg";
char *pstr = "hello world";
pstr=arr;//指针指向字符数组arr的首址

 

 

 

到这里我们明确了两点:

 

  1. 字符串的指向可以修改
  2. 不能通过对字符串的解引用来修改字符串常量的值

 

那么,下面这段代码是否正确?

 

#include<stdio.h>
int main() {
	char* pstr;
	char arr[] = "12345";
	pstr = arr;
	*pstr = 'a';
	printf("%s",arr);
}

  

是可以的。因为pstr指向字符数组arr,字符数组的数据存储单元可以修改。

 

输出的结果是:

 

  •  pstr指向arr的首址

  •  pstr是char类型,占一个字节的大小

  •   *pstr就代表字符数组arr的第一个元素对应的数据存储单元。

  • 所以这里修改了字符数组的第一个元素的内容,将第一个字符'h',改成了'a'

 

这一节的内容就到这里,后面会陆续更新C语言其他内容:指针、字符串的输入输出、指针与数组等难点内容

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值