字符串赋值给字符指针(char *a="hello")的正确理解方式
对于语句 char *a="hello";
对于这个声明方式,会造成的误解是:声明了一个字符指针(它会指向一个位置),将“字符串”赋值给 指针表达式"*a"所指向的地址。但正解是:声明了一个字符指针后,并用字符串常量的第一个字符的地址赋值给指针变量a。
即正确顺序是:
- 1.分配内存给字符指针;
- 2.分配内存给字符串;
- 3.将字符串首地址赋值给字符指针;
这里有两点需要考虑清楚的地方:
①*a只是指向一个字符。举例如下:
#include <iostream>
#include <string>
using namespace std; int main() { char *a ="abcdefg";
cout << "输出字符: " << *a << endl;
cout << "第二次输出字符: " << *(a+) << endl;
cout << "输出字符串: " << a << endl; return ;
}
结果如下
输出字符: a
第二次输出字符: b
输出字符串: abcdefg
② 若字符串常量出现在在表达式中,代表的值为该字符串常量的第一个字符的地址。所以”hello”仅仅代表的是其地址。
原声明方式相当于以下声明方式:
char *a;
a="hello";/*这里字符串"hello"仅仅代表其第一个字符的地址*/
1.但还是不明白为什么字符串可以赋值给字符指针变量
char *p,a='';
p=&a; //显然是正确的,
p="abcd"; //但为什么也可以这样赋值??
双引号做了3件事:
1.申请了空间(在常量区),存放了字符串
2. 在字符串尾加上了'/0'
3.返回地址
返回的地址,赋值给了指针变量p
2.以char *p = “hello”为例,把p换成数组,然后再赋值就不行了
字符串常量"hello"出现在一个表达式中时,"hello"表达式使用的值就是这些字符所存储的地址(在常量区),而不是这些字符本身。
所以,可以把字符串赋值给指向字符的指针p,而不能把字符串赋值给一个字符数组。
char a[10] = “hello”; //这样可以,这种情况是c语言初始化所支持的
如果写成char a[10]
然后 a = “hello” 这样就错误了。
因为同样是a数组,char a[10] = “hello”;这种是数组的初始化,和a[0] = ‘h’ a[1] = ‘e’…是一个道理
但是换成char a [10],然后a = “hello”是不行的,“hello”赋值的值是一个地址,而a虽然也有地址,与指针不同,指针的值是地址,而数组的值虽然同为地址,却是一个常量,不能给常量赋值
代码测试
#include <iostream>
#include <string> using namespace std; int main() {
char *p = "hello";
cout << p << endl;
char a[];
a = "hello";
return ;
}
报错 error C3863: array type 'char [10]' is not assignable
而修改后,正常运行
#include <iostream>
#include <string> using namespace std; int main() {
char *p = "hello";
cout << p << endl;
char a[] = "hello"; //数组初始化
return ;
}
字符数组,字符指针,字符串常量 知识回顾
1.以字符串形式出现的,编译器都会为该字符串自动添加一个0作为结束符,如在代码中写 "abc",那么编译器帮你存储的是"abc\0"
2."abc"是常量吗?
1.当作为字符数组初始值的时候,"abc"不是常量
char str[] = "abc";
因为定义的是一个字符数组,所以就相当于定义了一些空间来存放"abc",而又因为字符数组就是把字符一个一个地存放的,所以编译器把这个语句解析为
char str[] = {'a','b','c','\0'};
2.当赋值给 字符指针变量的时候:如char* ptr = "abc" 此时是常量
char* ptr = "abc" //规范不允许这种c的写法
规范写法
const char* ptr = "abc";
因为定义的是一个普通字符指针,并没有定义空间来存放"abc",所以编译器得帮我们 找地方来放"abc",显然,把这里的"abc"当成常量并把它放到程序的常量区是编译器 最合适的选择。简言之,如果char* ptr = "abc";写在函数体内,那么虽然这里的"abc\0"被 放在常量区中,但是ptr本身只是一个普通的指针变量,所以ptr(指针)是被放在栈上的, 只不过是它所指向的东西(值)被放在常量区罢了
3.数组的类型是由该数组所存放的东西的类型以及数组本身的大小决定的
如char s1[3]和char s2[4],s1的类型就是char[3],s2的类型就是char[4], 也就是说尽管s1和s2都是字符数组,但两者的类型却是不同的
4.字符串常量的类型可以理解为相应字符常量数组的类型
如"abcdef"的类型可以看成是const char[7]
5.sizeof是用来求类型的字节数的。
如int a;那么无论sizeof(int)或者是sizeof(a)都 是等于4,因为sizeof(a)其实就是sizeof(type of a)
6.对于函数参数列表中的以数组类型书写的形式参数,编译器把其解释为普通 的指针类型
void func(char sa[],int ia[],char *p) 则sa的类型为char*
ia的类型为int*
p的类型为char*
7.根据上面的总结,来实战一下
1)对于char str[] = "abcdef";就有sizeof(str) == 7,因为str的类型是char[7] str本身可变
2)也有sizeof("abcdef") == 7,因为"abcdef"的类型是const char[7] 字符串常量
3)对于char *ptr = "abcdef";就有sizeof(ptr) == 4,因为ptr的类型是char*,即
#include <iostream>
#include <string>
using namespace std;
int main() {
char *p = "hello";
cout << sizeof(p) << endl; //
cout << sizeof(char *) << endl; //
return ;
}
4)对于char str2[10] = "abcdef";就有sizeof(str2) == 10,因为str2的类型是char[10]
5)对于void func(char sa[100],int ia[20],char *p);
sizeof(sa) == sizeof(ia) == sizeof(p) == ,
因为前面有说过编译器把数组类型的书写的形参,解释为普通的指针类型
sa的类型是char*, ia的类型是int*,p的类型是char*
对于C/C++中的 字符指针和字符数组,总是在碰到的时候无法确定而不得不现场测试,来确定末尾是否包含'\0',函数到底如何使用等等。真是劳民伤财,现在总结一下:
字符指针的赋值
(1)指向一个字符串常量
char *src = "abcded"; //这种方式由系统自动给该字符指针指定了一个内存中的位置,并且该位置的字符数组为{'a', 'b', 'c', 'd', 'e', 'd', '\0'};
如果此时再次对 src赋值,src = "mmmt", 则src指向另外一个由系统指定的内存块(由"mmmt"本身返回)。这种方式赋值的src为一个指向字符串常量指针,不能对src指向的位置的内容做改变的操作,即不能执行 *src = 'a', *(src+1) = 't' 等操作;但是可以改变src指向的位置,即像之前的 src = "mmmt";
(2)指向一个字符数组
char tmp[4] = {'a', 'c', 'e', 'f'};
char* src = tmp;
(3)使用 new,然后可以像字符数组一样赋值,即指向一个字符数组
char* src = new char[10]; //这种方式由程序在堆内存上开辟了一个数组,并将地址赋值给src
字符串常量和字符数组比较
(1)字符串常量由系统自动分配一个内存区域,且该区域中的内容不能改变(即无法通过指向该字符串的指针进行修改);
(2)字符数组或者为系统自动分配的全局数据区或栈上的内存,或者通过new操作来分配的堆上的内存,字符数组中的内容可变(即可以通过指向该字符数组的指针进行修改)。
(3)字符数组中不默认含有'\0',除非明确赋值,而字符串常量在末尾自动含有 '\0'.
strcpy的使用
(1)用strcpy时候, 如果源字符串是一个字符指针,则没有问题,因为字符指针自动带'\0',在'\0'位置复制结束;
而如果源是一个字符数组(即将字符数组转换为字符指针来使用),则将会从字符数组的首地址开始复制,如果字符数组中明确指定了'\0'元素,则会在'\0'处停止,而若没有'\0'元素,则程序可能会不停的复制,直到在程序的内存中碰到'\0',这样可能会得到不希望的结果。
字符串赋值给字符指针(char *a="hello")的正确理解方式的更多相关文章
- 【转】C语言中,为什么字符串可以赋值给字符指针变量
本文是通过几篇转帖的文章整理而成的,内容稍有修改: 一. C语言中,为什么字符串可以赋值给字符指针变量 char *p,a='5';p=&a; //显然 ...
- C语言中,为什么字符串可以赋值给字符指针变量
转载于:http://www.cnblogs.com/KingOfFreedom/archive/2012/12/07/2807223.html 本文是通过几篇转帖的文章整理而成的,内容稍有修改: 一 ...
- C# 接收C++ dll 可变长字节或者 字符指针 char*
网络上查找到的几乎都是 需要提前固定知道 接收字符(字节)数据的大小的方式,现在的数据大小方式 不需要提前知道如下 思路: 1 .C++,返回变长 指针或者字节 的地址给C# 接收,同时返回 该地址的 ...
- C语言基础复习:字符,字符数组,字符串,字符指针
1. 概述2. 字符2.1 字符定义和大小2.2 字符的输入和输出2.3 字符的计算3. 字符数组3.1 字符数组的定义和大小3.2 字符数组的输入和输出3.3 字符数组的计算4. 字符串4.1 字符 ...
- c++字符指针
对于C/C++中的 字符指针和字符数组,总是在碰到的时候无法确定而不得不现场测试,来确定末尾是否包含'\0',函数到底如何使用等等.真是劳民伤财,现在总结一下: 字符指针的赋值 (1)指向一个字符串常 ...
- VS2019 字符串对指针char*赋值编译器报错原因及解决方法
2019-05-26 21:55:08 前几天在敲代码时,将字符串“Hellow world!”赋值给指针char*类型指针时编译器报错的问题 网上搜索后发现 char*是历史遗留问题,如果程序修 ...
- 字符数组,字符指针,字符串常量,以及sizeof的一些总结
1.以字符串形式出现的,编译器都会为该字符串自动添加一个\0作为结尾 如在代码中写"abc",编译器帮你存储的是"abc\0". 2.数组的类型是由该数组所存放 ...
- C++ code:char pointers and char arrays(字符指针与字符数组)
C-串的正确赋值.复制.修改.比较.连接等方式. #include<iostream> #pragma warning(disable: 4996)//这一句是为了解决“strrev”出现 ...
- Delphi 的内存操作函数(1): 给字符指针分配内存( 给字符指针(PChar、PWideChar、PAnsiChar)分配内存最佳的选择是StrAlloc。分配内存的时候会对字符串进行初始化)
马上能想到的函数有: GetMem AllocMem ReallocMem FreeMem GetMemory ReallocMemory FreeMemory New Dispose NewStr ...
随机推荐
- 为什么腾讯有QQ,还要推出微信?
在微信刚出现时候,很多人奇怪,为什么腾讯有QQ,还要推出微信? 一开始,我也认为它与QQ没有什么区别.有这种看法,是因为绝大多数时候,我都仅仅只使用即时聊天功能,微信上有的语音.视频.文字等等,这些在 ...
- Cocos Creator—定制H5游戏首页loading界面
Cocos Creator从1.0版本发布到现在也有一年多了,按理说一些常见的问题网上都有解决方案,例如"如何自定义首页加载进度条界面"这种普遍需求,应该所有人都会遇到的,因此也有 ...
- ColorUtil【Color工具类(color整型、rgb数组、16进制互相转换)】
版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 主要用于color整型.rgb数组.16进制互相转换(-12590395 <--> #3FE2C5 <--> ...
- SublimeText 修改文件扩展名的默认语法高亮
平时经常使用sublime text3编辑matlab程序,但是sublime text使用的默认语法高亮是Object C,用起来很不方便,每次都需要在Sublime Text右下角手动点一下语法高 ...
- 学习ASP.NET Core Razor 编程系列十八——并发解决方案
学习ASP.NET Core Razor 编程系列目录 学习ASP.NET Core Razor 编程系列一 学习ASP.NET Core Razor 编程系列二——添加一个实体 学习ASP.NET ...
- JavaScript夯实基础系列(五):类
JavaScript中没有类,是通过使用构造函数和原型模式的组合来实现类似其它面向对象编程语言中"类"的功能.ES6引入的关键字class,形式上向其它面向对象编程语言靠拢,其 ...
- Spring Cloud番外篇-001
熔断监控:Hystrix Dashboard Hystrix Dashboard是一款针对Hystrix进行实时监控的工具,通过Hystrix Dashboard可以直观地看到个Hystrix Com ...
- Java使用Aspose组件进行多文档间的转换操作
首先,祝大家新年快乐,2019诸事顺利,很久没有更新博客,今天要给大家说的是 ”Aspose“ 组件,作为2019年第一篇博客,希望大家能够多多支持,2019年要继续加油. 什么是Aspose? As ...
- XSS攻击之窃取Cookie
10 年前的博客似乎有点老了,但是XSS 攻击的威胁依然还在,我们不得不防. 窃取Cookie是非常简单的,因此不要轻易相信客户端所声明的身份.即便这个Cookie是在数秒之前验证过,那也未必是真的, ...
- Html和Css学习笔记-html基础知识
我的邮箱地址:zytrenren@163.com欢迎大家交流学习纠错! 此篇博客是我的复习笔记,html和css学的时间太久了,忘得差不多了,最近要使用一下,所以重新打开html的书略读,后记录了标签 ...