字符串初始化

在C++中基本数据类型并不包括string,string类型其实是一种类类型,通过STL函数库中的模板类basic_string 实例化得到。

int main ()
{
// string a = new string("123"); // 报错,需要将std::basic_string<char> * 转换到 std::basic_string<char>,
// 也就是编译器无法完成转换
string *a = new string("123");
string b = "456";
string *c = new string(b); // 并不是拷贝构造的浅拷贝 *c = "789"; cout << *a << endl; // 输出 123
cout << b[0] << endl; // 输出4
cout << c[0] << endl; // 输出789 return 0;
}

通过上面的代码,可以看出几点:

  1. 通过模板类实例化的类类型必须用string指针接收,指针步长为初始化变量的大小(上例中步长为3)
  2. 字符串常量赋值得到的类型可以用string类型接收
  3. 使用类对象对string类进行初始化,并不是浅拷贝,对指针的操作与原对象无关




string & 字符串常量 & char*

字符串常量在C++中的表示(const char):

int main()
{
// string a = 123; // 报错,invalid conversion from 'int' to 'const char*' // int a = "123"; // 报错,invalid conversion from 'const char*' to 'int' const char *a = "123"; // 通过
cout << a << endl; // 输出 123 string b = a; // 通过 delete a,b;
return 0;
}
  1. string类型在C++中被看做const char*,所以basic模板类对象的初始化需要用string*来接收
  2. 字符串常量也被看成是const char* 类型,所以用string接收字符串常量是合法的。


特殊的字符串常量操作:

既然上面提到字符串常量被看成是const char*类型,那么许多奇奇怪怪的用法就来了。

int main ()
{
*("123") = '2'; // 报错,无法使用解引用符对常量进行修改
cout << &("123") << endl; // 输出指针的地址
printf("常量\"123\"的所有元素:%c,%c,%c\n", *("123"), *("123"+1), *("123"+100));// 对指针的操作,输出1,2 const char *p = "123"; // 常量char指针的赋值 cout << (p == "123") << endl; // 因为指向同一个地址,输出 1
cout << (*p == "123"[0]) << endl; // 指向的元素是同一个元素,输出 1 cout << &(*("123"))<< endl; // 对某一元素的取地址,输出123 delete p;
return 0;
}

在上面的最后一个输出中,首先 *("123")得到的结果应该是字符'1',而对字符'1'取地址是没有问题的,为什么最后输出的不是正确地址而是字符串呢?


奇怪的字符指针取地址:

在回答问题之间,先来看下面这个例子:

int main ()
{
char p[5] = {'1','2','3','4'};
cout << p[0] << '\n' << &p[0] << endl; // 打印char数组第一个元素及其地址 int q[5] = {1,2,3,4,5};
cout << q[0] << '\n' << &q[0] << endl;// 打印int数组第一个元素及其地址 delete p,q;
return 0;
}



在2.1的代码中,我们将字符串常量赋值给了常量指针,并利用指针完成了字符串的输出,由此我们可知指针中储存的就是常量的首字符地址。即p = &("123"[0]) = &(p[0])。如下所示:

int main ()
{
const char* a = "123"; cout << (a == &("123"[0])) <<endl; // 输出1
cout << (a == &(a[0])) <<endl; // 输出1
cout << a <<endl; // 输出 123 int b[] = {1,2,3}; cout << (b == &(b[0])) <<endl; // 输出 1
cout << b << endl; // 输出 0x28fe90
return 0;
}

由于字符指针的指针的特殊性:字符指针可能会被认为代表一个字符串,而不是一个地址,在这种情况下,编译器会一直打印字符串,而不是地址。

而相应的其他数据类型就不存在这种问题了。

因此如果想要得到字符数组或字符串中某个元素的地址,可以将char类型强转为非char类型打印。

int main ()
{
const char* a = "123"; cout << &(a[0]) << endl;
cout << (void *)&(a[0])<< endl;
return 0;
}

结语

时间:2020/08/16 10:55

坐标:广东深圳

C++字符串与指针的更多相关文章

  1. c#编程指南(十) 平台调用P-INVOKE完全掌握, 字符串和指针

    可以说新手使用P-INVOKE最开始的头疼就是C#和C++的字符串传递,因为这里涉及到两个问题. 第一:C#的string和C++的字符串首指针如何对应. 第二:字符串还有ANSI和UNICODE(宽 ...

  2. 指向字符串的指针在printf与cout区别

    根据指针用法: * 定义一个指针, &取变量地址, int b = 1; int *a = &b; 则*a =1,但对于字符串而言并非如此,直接打印指向字符串的指针打印的是地址还是字符 ...

  3. C语言复习-字符串与指针

    C语言复习-字符串与指针 例一: [字符串处理 去除C代码中的注释] C/C++代码中有两种注释,/* */和//.编译器编译预处理时会先移除注释.就是把/*和*/之间的部分去掉,把//以及之后的部分 ...

  4. C语言之数组,字符串,指针

    一. 数组的定义 1.  数组初始化 初始化方式 int a[3] = {10, 9, 6}; int a[3] = {10,9}; int a[] = {11, 7, 6}; int a[4] = ...

  5. Swift中对C语言接口缓存的使用以及数组、字符串转为指针类型的方法

    由于Swift编程语言属于上层编程语言,而Swift中由于为了低层的高性能计算接口,所以往往需要C语言中的指针类型,由此,在Swift编程语言刚诞生的时候就有了UnsafePointer与Unsafe ...

  6. 「C」 数组、字符串、指针

    一.数组 (一)数组 概念:用来存储一组数据的构造数据类型 特点:只能存放一种类型的数据,如全部是int型或者全部是char型,数组里的数据成为元素. (二)数组的定义 格式: 类型 数组名[元素个数 ...

  7. c++学习day3(字符串_指针)

    1.字符串 1)三种形式 用双引号括起来的字符串常量:结尾会有一个'\0'字符,但该字符只占据字节数,不会使字符串长度增加. 存放于字符数组中,以'\0'字符结尾:数组元素个数应至少为字符串长度+1 ...

  8. 指向字符串的指针和char类型的数组

    指针数组的效率比二维字符数组的效率高 指针数组不能修改字符串字面量,而二维字符数组中的内容可以更改

  9. C语言程序设计--字符串与指针及数组与指针

    数组的基本知识 数组的定义 #define SIZE 5 int array_int[5]; //未声明初始化,默认填零 float array_float[5] = {1.01, 2.23, 3.1 ...

  10. VS2019 字符串对指针char*赋值编译器报错原因及解决方法

    2019-05-26   21:55:08 前几天在敲代码时,将字符串“Hellow world!”赋值给指针char*类型指针时编译器报错的问题 网上搜索后发现 char*是历史遗留问题,如果程序修 ...

随机推荐

  1. 【保姆级教学】新手第一次搭建vue项目和初始化

    前端项目初始化步骤 安装vue脚手架 通过vue脚手架创建项目 配置vue路由 配置Element-UI组件库 配置axios库 初始化git远程仓库 将本地项目托管到github或者码云上 通过vu ...

  2. MediaDevices.getUserMedia()

    MediaDevices.getUserMedia() 会提示用户给予使用媒体输入的许可,媒体输入会产生一个MediaStream,里面包含了请求的媒体类型的轨道.此流可以包含一个视频轨道(来自硬件或 ...

  3. Spring bean作用范围

    1,singleton Spring ioc 容器中仅有一个 Bean 实例,Bean 以单例的方式存在:2,prototype 每次从容器中调用 Bean 时,都返回一个新的实例:3,request ...

  4. spring boot中使用mybatis的注意点!!!

    1 生成的mapper接口上打上注解 2 在pom.xml中需要导入mysql(根据需要),jdbc和mybatis的依赖 3 在主类上设置扫描 4 com.mysql.cj.exceptions等报 ...

  5. Java—匿名对象/内部类/访问修饰符/代码块

    匿名对象 匿名对象是指创建对象时,只有创建对象的语句,却没有把对象地址值赋值给某个变量. //创建一个普通对象 Person p = new Person(); //创建一个匿名对象 new Pers ...

  6. go微服务系列(四) - gRPC入门

    1. 前言 2. gRPC与Protobuf简介 3. 安装 4. 中间文件演示 4.1 编写中间文件 4.2 运行protoc命令编译成go中间文件 5. 创建gRPC服务端 5.1 新建Produ ...

  7. HTML5+css3 的开心网游戏页面

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...

  8. 剑指Offer——II平衡二叉树

    class TreeNode: def __init__(self, x): self.val = x self.left = None self.right = None # 这道题使用中序遍历加上 ...

  9. Ubuntu18.04安装Nautilus-actions自定义文件管理器鼠标右键列表

    sudo add-apt-repository ppa:daniel-marynicz/filemanager-actions #需要添加源 sudo apt-get install filemana ...

  10. day6 函数

    1.关键字参数     给实参对应的形参   调用函数时 设置关键字参数,形参=实参,把实参固定给那个形参 2.元组的可变(不定长参数)的使用      可变参数可以接收任意数量的普通的形参,并且组包 ...