strlen计算字符串的长度,以'\0'为字符串结束标志

strlen()是函数,可以计算字符串的长度,不管是数组还是指针,只要遇到第一个‘\0’就为止,hello字符串是这样的{‘h’, ‘e’,‘l’,‘l’,‘\0’,‘o’}的所以strlen(“hello”) = 4。

sizeof是分配的数组实际所占的内存空间大小,计算数据空间的字节数。

例如:

char *str = "1111111abcd";

char str1[9] = {1};

sizeof(str)  = 4;    //是指指针所占的字节大小,在c/c++中一个指针占4个字节(32位系统)

sizeof(str1) = 9;  //字符类型占一个字节,8位

sizeof()是运算符,由于在编译时计算,因此sizeof不能用来返回动态分配的内存空间的大小。返回值跟这些里面所存储的内容没有关系。

具体而言,当参数分别如下时,sizeof返回的值含义如下:

数组-编译时分配的数组空间大小

指针-存储该指针所用的空间大小

类型-该类型所占的空间的大小

对象-对象的实际占用空间大小

函数-函数返回类型所占空间的大小

32位:指针都是 4个字节   注意:int *p; sizeof(p)=4;     但sizeof(*p)相当于sizeof(int);

64位:指针都是 8个字节

int 都是4个字节;char都是1个字节

fromhttps://blog.csdn.net/lby978232/article/details/71172713

from :https://www.cnblogs.com/bixiaopengblog/p/8036429.html


简单的说,这两者的区别是:

  1. char []定义的是一个字符数组,注意强调是数组
  2. char * 定义的是一个字符串指针,注意强调是指针

数组表示字符串数组,数组的每一个元素都是一个字符,修改一个数组指的是修改数组的值,即改变其中一个或者多个元素的值;而指针表示这是一个地址,其值就是一个地址,并没有字符串值的概念,修改一个指针只是把指针指向别的地址或者NULL;

定义数组变量ch1和字符串指针ch2。

1   char ch1[] = "ABCDEFGH";
2   char * ch2 = "abcdefgh";
  1. ch1的内容存储在函数栈中,可以被修改,函数一旦返回空间就被释放。
  2. ch2的内容保存在只读数据段中,不可被修改,其空间不会被释放。

总结一下,回到开头提到的:

  1. ch1强调的是数组,ch2强调是指针,在各自作用域范围内有效,可操作。
  2. 作为数组可以操作的是数组值,那么数组内容是可以改变的。
  3. 作为指针可以操作的是指针值,那么指针内容是可以改变的,即指向另一个地址,但不能改变指针指向的内容。换句话说就是可以修改指针的值,但不能修改指针值的值。

注意   指针内容   和    指针指向的内容    这两个说法的不同之处。前者是地址,后者是地址中存的变量。

char * 和char[]的初始化操作有着根本区别:

测试代码:

char *a=”Hello World”; 
char b[]=”Hello World”; 
printf(“%s, %d\n”,”Hello World”, “Hello World”); 
printf(“%s, %d %d\n”, a, a, &a); 
printf(“%s, %d %d\n”, b, b, &b); 
结果:

   char *a=”Hello World”; 在常量区存了”Hello World”,在栈中存放指针a.所以printf(“ %d\n”, “Hello World”);输出的是Hello World在常量区的地址;printf(“ %d %d\n”,  a, &a);第一个输出是a中存放的地址,这个地址就是“Hello World在常量区的地址”,二第二个输出的是:指针a在栈中的位置。

结果可见:尽管都对应了相同的字符串,但”Hello World”的地址 和 a对应的地址相同,与b指向的地址有较大差异;&b==b (因为char b[]=”Hello World”整体都是存放在栈中。b就是个数组名,我们可以理解为在栈位置2030316处,开始存放H,下个位置存放e.......最后存放d)

我们知道,局部变量都创建在栈区,而常量都创建在文字常量区,显然,a、b都是栈区的变量,但是a指向了常量(字符串常量),b则指向了变量(字符数组),指向了自己(&b==b==&b[0])。

说明以下问题:

char * a=”string1”;是实现了3个操作:

1声明一个char*变量(也就是声明了一个指向char的指针变量,在栈中)。 
2在文字常量区中开辟了一个空间存储字符串常量”string1”。 
3返回这个文字常量区的地址,作为值,赋给这个字符指针变量a ,存放在栈中

最终的结果:指针变量a指向了这一个字符串常量“string1” (注意,如果这时候我们再执行:char * c=”string1”;则,c==a,实际上,只会执行上述步骤的1和3,因为这个常量已经在内存中创建)

PS: 实际上, char * a=”string1”; 的写法是不规范的! ”string1”默认是常量
    因为a指向了即字符常量,一旦strcpy(a,”string2”)就糟糕了,试图向只读的内存区域写入,程序会崩溃的!尽管VS下的编译器不会警告,但如果你使用了语法严谨的Linux下的C编译器GCC,或者在windows下使用MinGW编译器就会得到警告。

所以,我们还是应当按照”类型相同赋值”的原则来写代码: const char * a=”string1”; 保证意外赋值语句不会通过编译。

char b[]=”string2”;则是实现了2个操作:

1、声明一个char 的数组, 
2、为该数组“赋值”,即将”string2”的每一个字符分别赋值给数组的每一个元素,存储在栈上。 
最终的结果:“数组的值”(注意不是b的值)等于”string2”,而不是b指向一个字符串常量。

小结

char * a=”string1” 
char b[]=”string2”;

2.a是一个指针变量,a的值(指向)是可以改变的,但a指向的是一个字符串常量,即指向的区域只读,指向的区域的内容不可改变;

3.b是一个指针常量,一个char型数组的名字,也是该数组首元素的地址,是常量,b的值(指向)不能变;但b指向的目标(数组b在内存中的区域)的内容是可变的

4.作为函数的声明的参数的时候,char []是被当做char *来处理的!两种形参声明写法完全等效!

举例说明:

char str1[] = "abc";
char str2[] = "abc";
const char str3[] = "abc";
const char str4[] = "abc";
const char *str5 = "abc";
const char *str6 = "abc"; //指向常量的指针
char *str7 = "abc";    //指向变量的指针,这种写法好像会报错吧??因为"abc"是常量
char *str8 = "abc";
cout << (str1 == str2) << endl;
cout << (str3 == str4) << endl;
cout << (str5 == str6) << endl;
cout << (str7 == str8) << endl;

结果:0  0   1   1.

1、char str1[] = "abc":

这里的"abc"是一个常量,首先会在常量存储区里存储"abc"这个常量,然后会因为"abc"被赋值给str1[],所以在栈中开辟一段内存,内存大小为4个节点(char数组后会自动加一个'\0'),然后就有一个"abc"被保存在栈中

同理,str2[]中的"abc"也是保存在栈中,只是地址不同。

到此,有三个"abc"被保存起来,一个在常量存储区,另外两个在栈中。

2、const char str3[] = "abc":

对于这种被const(常量)修饰起来的变量,一般也是被保存在常量存储区,但是对于const数组来讲,系统不确定符号表是否有足够的空间来存放const数组,所以还是为const数组分配内存的。所以str3指向的是栈上的"abc"。????

同理,str4[]也是保存在栈中,地址不同。

3、const char *str5 = "abc":

因为"abc"在常量存储区中保存有一份(即使没保存,这样的操作也会新建一份),这里str5定义的时候,嘿,我见过这个,str5就可以开心的直接指向"abc"所在的常量区的地址

同理str6,str7,str8。与const没有半毛钱关系,const只是使得str5和str6无法指向新的字符串常量(也就是新的地址,因为const修饰,变成了常量,即地址值不能再改变了)。

from:https://blog.csdn.net/u013654125/article/details/79758286

插一句,c++内存被分为5个区,分别是堆、栈、自由存储区、全局/静态存储区和常量存储区。


*p++和(*p)++的区别

*p++:是指:指针指向下一个地址,即地址加一,然后取出此时p所指的数据的值

(*p)++:是指将*p所指的数据的值加一。

C编译器认为*和++是同优先级操作符,且都是从右至左结合的,所以*p++中的++只作用在p上,和*(p++)意思一样;在(*p)++中,由于()的优先级比*和++都高,所以++作用在()内的表达式*p上。

我们先来理解:p++和++p

p=3;
printf("%d",p++);   //  3   ,先输出3,后加1
printf("%d",p);       //4
printf("%d",++p);      //  5, ++p是先加一,后赋值

实例:

int main()
{
    int a[]={1,8,5,9,12,6};
    int *p=a;
    int *q=a;
    int x=*p++;   //先取指针p指向的值(数组第一个元素1)赋值给x,再将指针p自增1,此时指向a[1];  x=1
    int y=(*q)++;  //先取指针q指向的值(数组第一个元素1)赋值给y,再将指针q指向的值自增1; y=1,但执行完a[0]=2
    cout<<y<<endl<<((*q)++) <<endl<<x<<endl<<(*++p)++<<endl<<a[0];
}

((*q)++) 输出:q指向的值,此时是2,复制后再将指针q指向的值自增1,即a[0]=3;

(*++p)++:根据运算符优先级,先计算括号内内容,++p,首先自增p,此时p指向第3个元素,即指向a[2];然后通过*得到a[2];后置++不立即改变a[2]的值(输出5),而在此表达式之后a[2]值为6.

  1. *++p 先将指针p自增1(此时指向数组第二个元素),* 操作再取出该值
  2. ++*p 先取指针p指向的值(数组第一个元素1),再将该值自增1,

可以看出这两个操作与*p++和(*q)++,正好是反着操作,前者先计算后赋值,后者是先赋值后计算。

from:https://zhidao.baidu.com/question/494193523.html

C++ 易混淆的概念-sizeof和strlen、char* 和char[]、*p++和(*p)++相关推荐

  1. C语言中易混淆的标识符,C语言指针中易混淆的概念

    C语言指针中易混淆的概念 一.数组指针与指针数组的区别 考虑数组的指针的时候我们要同时考虑类型和维数这两个属性.换一句话,就是说一个数组排除在其中存储的数值,那么可以用类型和维数来位置表示他的种类. ...

  2. 第十七节:易混淆的概念(静态和非静态、拆箱和装箱)

    一. 静态和非静态 1. 概念介绍 ① 静态类(被static修饰) vs  普通类(没有被static修饰) ② 静态成员:被static修饰的成员,比如:静态方法.静态字段等 ③ 普通成员(实例成 ...

  3. 关于地名地址易混淆的概念和wfs-G服务如何实现

    首先,我们国内对地名地址这两个词的理解要清楚. 地名,是地理实体的专有名称. 地理实体,现实世界中具有共同性质的自然或人工地物. 地址,具有地名的某一特定空间位置上自然或人文地理实体位置的结构化描述. ...

  4. 等价无穷小代换易混淆的概念错误!!用泰勒展开,以后!

    注意:第一个解法的错在第一步的无穷小代换! 分析如下: 所以为了计算方便就直接将g(x)替换为f(x). 那么再来看这个题解答第一步错误性: 分析: 根据 令,其中,替换只能替换整个的一部分,而非整个 ...

  5. 有限元分析几个易混淆的概念

    本文转自-公众号:有限元仿真分析 原文链接:https://mp.weixin.qq.com/s/odNpaNU0L1i1X7xpUTc0aQ 单元形函数 单元形函数是一种数学函数,规定了从节点自由度 ...

  6. 【C#小知识】C#中一些易混淆概念总结(三)---------结构,GC,静态成员,静态类...

    目录: [C#小知识]C#中一些易混淆概念总结 [C#小知识]C#中一些易混淆概念总结(二) ---------------------------------------分割线----------- ...

  7. 【C#小知识】C#中一些易混淆概念总结(七)---------解析抽象类,抽象方法

    目录: [C#小知识]C#中一些易混淆概念总结--------数据类型存储位置,方法调用,out和ref参数的使用 [C#小知识]C#中一些易混淆概念总结(二)--------构造函数,this关键字 ...

  8. C#中一些易混淆概念总结--------数据类型存储位置,方法调用,out和ref参数的使用...

    这几天一直在复习C#基础知识,过程中也发现了自己以前理解不清楚和混淆的概念.现在给大家分享出来我的笔记: 一,.NET平台的重要组成部分都是有哪些 1)FCL (所谓的.NET框架类库) 这些类是微软 ...

  9. 数字电视的几个易混淆概念

      了解数字电视需要分清的五个易混淆概念 2008年北京奥运会一天天在临近,奥组委承诺北京奥运会将使用高清信号直播.为了让全国的观众收看到在自己家门口举行的这一盛大的体育赛事,广电总局已经开始在全国推 ...

最新文章

  1. 分享一个针对触摸设备优化的图片幻灯jQuery插件 - touchtouch
  2. LIst和map的遍历
  3. win10系统定位服务器地址,win10系统定位服务器地址
  4. Spring学习3之IOC创建对象的方式
  5. CVPR 2017 《Deep Feature Flow for Video Recognition》论文笔记
  6. java怎么学好 用好接口_Java公开课|Java的实现接口怎么用,这才是学习好Java必备的实用函数,你会吗...
  7. .NET 中的 Worker Service 入门介绍
  8. 跨域资源共享 CORS 详解
  9. datatable 转list ,list转datatable
  10. 北京理工大学计算机系郭伟,【记忆辉煌2014】品学兼优榜样——郭伟(2012级研究生)...
  11. Mysql取分组中前N条记录
  12. jinja Comments
  13. python 元组的一点问题
  14. 使用HttpURLConnection+AsyncTask访问webservice接口(返回json字符串)
  15. Mysql源码编译安装主从复制
  16. Hyperledger Fabric Composer安装blockchain explorer
  17. html5 语音直播,一种基于HTML5浏览器的音视频直播方法与流程
  18. WPF界面设计的模式
  19. 计算机硬盘的常用分区工具,磁盘分区工具,详细教您硬盘分区工具diskgenius怎么使用...
  20. 置信区间 置信水平 边际误差

热门文章

  1. java后端简历项目经历_为了面试字节跳动后端开发岗(Java)鬼知道我经历了什么.....
  2. Selenium常用API的使用java语言之6-WebDriver常用方法
  3. 基于jQuery日历插件制作日历
  4. python3-开发进阶补充Django中的文件的上传
  5. 北航校赛2014 预赛 题解
  6. discuz 表结构
  7. Flash中textInput限定中英文字数
  8. 不同.net版本实现单点登录
  9. 如何找回系统盘丢失的空间
  10. vue中v-on指令的使用之Vue知识点归纳(四)