一、char,char*,char a[], char *a[], char **s 的区别与联系

C语言中的字符串是字符数组,可以像处理普通数组一样处理字符串。

可以理解为在内存中连续存储的字符。

  1. 从实用主义而言,我们先给出结论。

    我们会用到的一般有两种。

    · 声明一个字符串:char* a = "abcdefg";

    · 声明一组字符串:char* a[] = {"China","French","America","German"};

  2. 原理

    这里只考虑静态数组,在内存中划分了连续的地址空间。字符串以“\0”为结尾符。

  3. 地址/字符串的输出与查看

    假设a是一个指针变量,为了查看这个指针变量的内容,我们可以用%p输出查看。printf("%p",a);

    查看这个字符型指针变量的字符串:printf(%s,a);

    注意指针变量也是存在内存里的,自己也有个地址。用&a表示。

  4. char*

    很多资料中会写成char* a而不是char a,事实上我本科学C语言的时候一直认为是char (a),但其实前者可以一起理解:

**char*: 用于声明一个只是保存字符串首地址的指针变量**

  1. 符号优先度

    a[]的优先度大于*a。

  2. 指针与二级指针

    这里可以回到我们开头所说的两种定义了。

    第一种:

    · 声明一个字符串:char* a = "abcdefg";

    这个理解起来非常容易,定义了一个字符串"abcdefg",在连续的内存空间里存储,并且定义了一个保存这个字符串的首地址的指针变量a,所以a的值为字符’a‘所存的地址。

    如果我们用printf("%s",a),将输出abcdefg。

    · 声明一组字符串:char* a[] = {"China","French","America","German"};

    a[]是一个4长数组,里面存了四个指针变量:a[0],a[1],a[2],a[3]。分别指向字符串China,French,American和German的首地址。

    而a[]的值也就是a也就是这个数组的首地址,也就是a[0]的地址。

    ·二级指针

    二级指针就是指针的指针。在第二种声明中,我们用到的二级指针:

    a[0]是指向字符串China的指针,而a是指向a[0]的指针。

    二级指针的赋值与声明:char **s = a; //定义了一个名为s的二级指针,指向a的地址

    即,*s=a[0],也就是printf("%s",*s)

#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include <string>
#include <iostream>
using namespace std; int main(){
char* a[] = {"China","French","America","German"};
printf("%p\n",a);
for (int i = 0; i < 4; i++){
printf("a[%d] is %p\n",i, a[i]); //用于查看a[i]的内容(所指的目标的地址值)
printf("address a[%d] is %p\n",i, &a[i]); //用于查看a[i]自己的地址
//printf("%d\n",sizeof(&a[i]));
printf("%d\n",sizeof(a[i])); //用于查看a[i]自己的大小(指针变量的大小 4字节)
printf("%s\n",a[i]); //用于打印指针变量的字符串
}
char **s = a; //定义二级指针s
printf("%p\n",s); //输出s=a[0]的地址
printf("%s\n",*s); //输出*s=a[0]所指的字符串
cout << a[0][2]; //i
cout << (*s)[2]; //i
system("pause");
}

运行结果:

·二级指针的用处:二维数组传参

参考另外一篇博文:【C/C++】二维数组的传参的方法 https://www.cnblogs.com/kinologic/p/13958685.html



这种二级指针的每一

二、C语言中char* 和const char*的区别

const char*char*

首先,char*:用于声明一个【只是保存字符串首地址的】指针变量

const char *:指针指向的内容不可变,但指针本身可以再赋值。

C 语言中char* 和const char*的区别:

一、含义的区别

char* 表示一个指针变量,并且这个变量是可以被改变的。

const char*表示一个限定不会被改变的指针变量。

二、模式的区别

char*是常量指针,地址不可以改变,但是指针的值可变。

const char*是指向常量的常量指针,地址与值均不可变。

三、指针指向的内容的区别

一句话总结来说,就是指针(地址)里放的东西能不能变的区别。

char定义的指针的地址里面存的东西可以变,但是const char定义的指针的地址里面存的东西不能变,要修改const char#定义的指针指向的东西的值,只能新开辟其他的地址里面的东西,然后把地址的值改掉。



可以看到,将p指向的内容由123改为456之后,p里面存的的地址变了。



我们把原来的p里面所存的123的地址再输出,发现还是123.也就是地址里存的东西不变。

char*指针指向的【内容】是可以改变的,是不固定的。赋值后在数据传递的过程中允许改变。

const char*指针指向的【内容】是固定的,不可改变的。对传入的参数,不会对指针指向的内容进行修改

【??问题】



同样的操作我对char*又做了一遍,发现好像没有区别?

四、意义的区别

char* str确保str这个指针不会改变,但是这个指针里面的内容可以改变。

const char* str确保*str的内容不会改变,也就是用str这个指针无法改变str这个指针指向的地址的内容,但是可以改变这个指针。

可以看出两种类型不同,不可以将const char型变量赋值给char型变量。



但是可以通过强制转换赋值:

三、const [类型]* p 和[类型]* const p的区别与联系

【C/C++】字符数组:char,char*,char a[], char *a[], char **s 的区别与联系/const char*和char*的区别的更多相关文章

  1. Java中如何拆分字符串为字符数组

    题目:输入一串字符,由(){}[]组成,判断是否所有的括号都是闭括号,是的返回TRUE,不是返回FALSE. /*输入字符串,拆解为字符数组 * 用函数s.charAt(i)来完成 * * */imp ...

  2. java io系列19之 CharArrayWriter(字符数组输出流)

    本章,我们学习CharArrayWriter.学习时,我们先对CharArrayWriter有个大致了解,然后深入了解一下它的源码,最后通过示例来掌握它的用法. 转载请注明出处:http://www. ...

  3. C语言中二维字符数组的定义和初始化

    本篇日志关于二维字符数组的定义和初始化.我相信这篇文章属于菜鸟级的,高手请直接无视. 一般来说,我们可能会希望定义一个二维字符数组并且在定义的时候就用一些字符串来初始化它.比如说: ][MAX_LEN ...

  4. 【C】字符串常量和字符数组

    此次博客是转载某位博主的文章,不过现在找不到了,所以先声明一下. 先贴一段代码: #include <stdio.h> int main(int argc, const char** ar ...

  5. C++中的字符数组、字符指、字符串针(腾讯)

    一.字符数组 1.定义时进行初始化的方式 (1)char c[12]={'I',' ','a','m',' ','h','a','p','p','y'};//最后两个元素自动补‘\0’(不是空格),其 ...

  6. C语言字符数组超细讲解

    看到标题,有不少朋友会想:字符数组不也是数组吗?为什么要单独拿出来讲哩?莫非它是朵奇葩? 哈哈,确实,一起来认识一下这朵数组界的奇葩吧! 一.字符数组的定义.引用.初始化 大家好!我是字符数组,看我的 ...

  7. 逗号字符的使用、字符数组与字符串数组、sizeof与strlen

    (1)连接两个表达式为一个表达式 for(ux=0,uxt=1;uxt<444;ux++,uxt++) 允许通过编译:他可以给FOR循环更多的初始化值: (2)一般定义的话要区别只有 字符数组 ...

  8. 字符数组char

     数组做sizeof的参数不退化,传递给strlen就退化为指针: #include<stdio.h> #include<stdlib.h> #include<strin ...

  9. QString和char字符数组之间的转换(QTextCodec.toUnicode方法,特别注意\0的问题)

    How can I convert a QString to char* and vice versa ?(trolltech) Answer:In order to convert a QStrin ...

  10. Delphi的字符(Char),字符串(String),字符串指针(PChar),字符数组arrayofchar(来自http://delphi.cjcsoft.net/论坛)

    Delphi有三种类型的字符: AnsiChar这是标准的1字节的ANSI字符,程序员都对它比较熟悉. WideChar这是2字节的Unicode字符. Char在目前相当于AnsiChar,但在De ...

随机推荐

  1. GoLang设计模式14 - 状态模式

    状态模式,顾名思义,是一种基于有限状态机制的设计模式.在这种设计模式中,行为是由相应的状态来决定的.接下来我们会用一个售卖机的例子来说明下状态模式.为了便于说明,我们把场景简化一下,假设有一台售卖机只 ...

  2. dotNET开发之MVC中Controller返回值类型ActionResult方法总结

    1.返回ViewResult视图结果,将视图呈现给网页 2. 返回PartialViewResult部分视图结果,主要用于返回部分视图内容 3. 返回ContentResult用户定义的内容类型 4. ...

  3. 通过修改host加速访问GitHub

    加速访问GitHub 原理:绕过 DNS 解析,直接使用本地的 DNS 记录进行直接跳转. 可以通过 http://ping.chinaz.com/ 链接查询github的DNS信息,例如,可以直接打 ...

  4. 使用.NET5、Blazor和Electron.NET构建跨平台桌面应用

    Electron.NET是一个嵌入了ASP.NET Core的Electron的封装,通过Electron.NET可以构建基于.NET5的跨平台的桌面应用,使得开发人员只需要使用ASP.NET Cor ...

  5. vite2 + vite.config.js 比较坑的环境变量,vite2模式的使用

    想在vite.config.js 里面判断一下环境,看看是不是开发环境,查了一下官网(https://cn.vitejs.dev/guide/env-and-mode.html),说是 可以使用 im ...

  6. oracle 创建空间索引

    1. 首先进行查询,判断数据是否已经建立相应的空间元数据 select * from user_sdo_geom_metadata t where t.table_name like '%表名%'; ...

  7. [Net 6 AspNetCore Bug] 解决返回IAsyncEnumerable<T>类型时抛出的OperationCanceledException会被AspNetCore 框架吞掉的Bug

    记录一个我认为是Net6 Aspnetcore 框架的一个Bug Bug描述 在 Net6 的apsnecore项目中, 如果我们(满足以下所有条件) api的返回类型是IAsyncEnumerabl ...

  8. C/C++ Qt MdiArea 多窗体组件应用

    MDI多窗体组件,主要用于设计多文档界面应用程序,该组件具备有多种窗体展示风格,其实现了在父窗体中内嵌多种子窗体的功能,使用MDI组件需要在UI界面中增加mdiArea控件容器,我们所有的窗体创建与操 ...

  9. Atcoder Regular Contest 072 C - Alice in linear land(思维题)

    Atcoder 题面传送门 & 洛谷题面传送门 首先求出 \(s_i\) 表示经过 \(i\) 次操作后机器人会位于什么位置,显然 \(s_0=D\),\(s_i=\min(s_{i-1},| ...

  10. BZOJ 4556 [HEOI2016/TJOI2016]字符串

    BZOJ 4556 [HEOI2016/TJOI2016]字符串 其实题解更多是用后缀数组+数据结构的做法,貌似也不好写. 反正才学了 sam 貌似比较简单的做法. 还是得先二分,然后倍增跳到 $ s ...