天天看点

游戏筑基开发之字符串、字符指针、字符数组的相关知识梳理(C语言)游戏筑基开发之字符串、字符指针、字符数组的相关知识梳理(C语言)

游戏筑基开发之字符串、字符指针、字符数组的相关知识梳理(C语言)

该文章大部分均为转载内容,对其进行梳理【点击跳转】

1.为什么可以将字符串常量赋值给字符指针变量?

char *p,a='5';
p=&a;                     //正确
p="abcd";              //正确
           

原因如下:

  字符串常量的双引号的作用:

  1. 在常量区申请内存保存该字符串

  2. 在字符串的尾部加上’\0’

  3. 返回该字符串在常量区的地址

即可以将该地址赋值给一个字符指针。

2.为什么字符串常量无法赋值给字符数组?

char *p = “hello”;//正确
char p1[10];
p1 = "hello";//错误
char p2[10] = "hello";//正确
           

  字符串常量双引号记录的是该字符串常量的地址,并不是字符串常量本身。char p2[10] = “hello”;可以是因为C语言支持该初始化方式。类似于p2[0] = ‘h’,p2[1] = ’e‘…

p1 = “hello”;这样是错误的,因为p1本身就是一个指针,指向大小为10个字节的内存空间,类似于指针常量,其指向无法修改。即无法给指针常量赋值。

TIPS:在void指针使用的时候,不能使用指针运算,应为void型编译器不能识别类型的长度(即指针所指对象的体积),p++这样就是不合法的,即不能进行数学运算,也不能使用*取值操作,想使用必须转换为其它的类型。

3.对字符串常量、字符指针、字符串常量知识的整理概述

  1. 以字符串形式出现的,编译器都会对该字符串末尾加上\0或者\000作为结束符,如在代码中“abc”,那么编译器存储的时候便是“abc\0”。
  2. “abc”一定是常量吗?

    答案是不一定。

    ①不是常量的情况:当“abc”作为字符数组的初始值就不是,如char str[] = “abc”;因为字符数组是将字符一个一个的存放起来,编译器解析为char str[4] = {‘a’,‘b’,‘c’,’\0‘};即如果char str[4]是一个局部变量的话,那么便在栈区上,不是常量。

    ②常量的情况:当“abc”赋值给一个字符指针变量时,如 char* ptr = “abc”;因为我们定义的是一个在栈区的普通字符指针,并没有定义任何内存空间来存放字符串常量“abc”。所以编译器把其存入内存中的常量区。因此即便是我们没有写成const char* ptr = “abc”;但是我们仍然不能操作ptr[0]=‘x’;因为ptr实际上指向的是一个常量,即ptr是一个常量指针,其指向的值不能修改。如果char* ptr = “abc”;写在函数体内,那么虽然这里的"abc\0"被放在常量区中,但是ptr本身只是一个普通的指针变量,所以ptr是被放在栈上的,而其指向在常量区,函数执行完毕ptr的内存空间被释放,即在栈区的内存空间被释放,但是"abc"仍然在常量区,未被释放。

    ③字符串常量的类型可以理解为相应字符常量数组的类型。

    如"abcdef"的类型就可以看成是const char[7]

    ④对于函数参数列表中的以数组类型书写的形式参数,编译器把其解释为普通的指针类型。

    如对于void func(char sa[100],int ia[20],char *p)则sa的类型为char*,ia的类型为int*,p的类型为char*。

4.为什么字符数组可以直接赋值给字符指针?

char a[10] ="hello";
char *p;
p = a;//正确
           

  char a[10]字符数组就是一个占用10个字节的连续地址空间。其首地址保存在a(指针常量)中。而p = a;就是将a记录的连续地址的首地址告知p,从而p指向的值就是"hello",且其保存了该连续地址的首地址。

继续阅读