前言
这个主要还是想说用指针和用数组操作一个字符串的区别在哪里,前面那个字符数组与字符串的话相信大家只要学过 C 语言肯定就知道他俩之间的区别在哪里
课堂
字符数组
char arr[10] = {'A','B','C','D','E','F'}; //编译器默认在结尾添加0x00
char arr[3] = {'A','B','C'}; //但是如果没有留出'\0'的空间,编译器就不会自动添加
char buffer[100] = ""; //定义了一个空字符串,字符串中每个字节默认初始为0x00
char buffer[] = ""; //这个数组长度只有1,且默认初始为0x00
所以我们在定义一个字符数组来表示一个字符串的时候,一定要记得在结尾加’\0’,如果不加的话一定要记得预留出空间,这样的话,编译器也可以帮你加上,否则在%s 输出的时候,这个会默认的把\0 前面的东西全部都输出,这样肯定是不对的
字符串
char names[] = “ABCDE”; //可以省略数组大小,但是此时的数组大小应该 6,因为编译器会自动在末尾加 0x00
char* p = “ABCDE”; //这个是将常量区中存储 ABCDE 字符串的首地址赋给 p,此时 p 的长度是 4 字节,常量区的字符 串虽然后面补 0,但是不能算到字符串的长度中,所以字符串的长度应为 5 字节
上面这两个其实就有点引出今天的重点了,这个会在下面具体讲,大家别急哈
字符串和字符数组的输出
char arr1[6] = {'A','B','C','D','E','\0'};
char arr2[6] = {'A','B','C','D','E',0}; //注意区分这里的0不是'0'
char arr3[6] = {'A','B','C','D','E'}; //只要比5大,数组的长度随便
char names[] = "ABCDE";
printf("%s\n",arr1);
printf("%s\n",arr2);
printf("%s",names);
char word[8];
scanf("%7s", word);//最多读7个字符
上面的结果都是一样的,都打印 ABCDE
字符串数组
这里给出它的两种形式
char a[][10] = {"hello","abcdefg"};
上面这个就相当于把常量区里面的字符串复制出来了一份,这句话你可能现在不理解,往后看就行了,看完这篇文章肯定会明白的,一开始的[]是空的,在这里就是1了,因为根据后面有两个字符串嘛,编译器自动会补的
char *a[] = {"hello","abcdefg"};
应该把这个*号写前面哈,这个就是明天那篇文章要说的指针数组,即是一个数组,但里面的每一个元素都是一个指针,这个就直接指到常量区了
常量区
这块早在一开始逆向的时候就讲过,现在再拿出来说一下,记住常量区里面的数据是可读不可写的,一般字符串等会放到常量区里面
重点—字符串的反汇编
char* x = "china"; //x中存的就是存储在常量区的china字符串的首地址,x指针型变量直接指向常量区中的存储 china字符串的首地址
char y[] = "china"; //这里也是常量区中的china字符串,但是与指针不同的是,这里会将字符串值复制一份到给y 字符数组变量分配的内存中(栈)
void Func(){
y[1] = 'A'; //可以修改
//*(x + 1) = 'A'; 无法修改
}
x 本身是可以再修改的:如x = "abc";
,但是 x 指向的字符串”china”是无法修改的!即 x 指向常量区的”china”字符串,现在想用 x 去改变常量区的字符串,也是不可以的。具体原因看下面反汇编!
- 首先来分析一下这个 char* x = “china”,因为
char *
类型宽度为 4 字节,VC 编译器的执行一个函数时默认提升的堆栈空间为 0x40 字节,现在由于定义了一个char
*类型的局部变量,所以会提升堆栈空间为 0x40 + 0x4 = 0x44;而后我们发现反汇编中的操作就是将已经存储在常量区(内存中的某个区域)的字符串”china”的首地址 0x422E80 存入了给 char类型变量 x 分配的内存中(main 函数的缓冲区),即char类型的变量 x 存储的是”china”字符串在常量区中的首地址
#include "stdafx.h"
int main(int argc,char* argv[]){
char* x = "china";
//char y[] = "china";
return 0;
}
所以可以发现使用指针类型变量 x 操作字符串其实就是修改常量区中的字符串,那么由于常量区中的数据可读不可写,所以编译器不允许使用*(x + 1) = 'A'
!
- 然后再来分析一下这个 char y[] = “china”,这是在 main 函数中定义了一个 char 类型的字符数组变量 y,接着给字符数组赋值”china”。但是在反汇编中可以发现,这里由于没有使用指针了,那么这个操作就是把已经存储在常量区的字符串”china”复制一份,将数据存到 main 中为字符数组变量 y 分配的 8 字节内存中(因为局部变量遵循本机尺寸)
#include "stdafx.h"
int main(int argc,char* argv[]){
char* x = "china";
//char y[] = "china";
return 0;
}
有的人会问,那如果把这个 char y[] = “china”;不放到 main 函数里面呢,事实上它还是会从常量区把字符串复制一份到全局变量区,操纵的依然不是常量区原本的字符串
所以:如果想对字符串做写操作,就定义成:char arr[] = "abc";
。如果只做读操作,定义成char* arr = "abc"
作业
无无无,很开心哈哈哈哈