C++字符数组、字符指针、strlen、sizeof总结

2024-05-03 15:08

本文主要是介绍C++字符数组、字符指针、strlen、sizeof总结,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

对于字符数组与字符指针:

1. 以字符串形式出现的,编译器都会为该字符串自动添加一个0作为结束符,如在代码中写"abc",那么编译器帮你存储的是"abc\0".

比如char a1[]="success";与char a2[] = {'s','u','c','c','e','s','s'};a1将会自动添加字符串结束符,a2不会自动添加。


2. 字符串直接量作为字符指针的初始值 

  "hello"是一个字符串直接量,编译器将其作为const char*处理,与之相关联的内存空间位于内存的只读部分,即允许编译器重用指向等价字符串直接量的引用以优化内存使用,

即使程序中使用了字符串直接量500次,编译器在内存中也只是创建了一个实例。例如: char *ptr = “hello”; 等价于 const char *ptr = “hello”;

字符串直接量"hello"关联的是只读内存,如果试图修改将出错,例如ptr[1] = ‘a’;是会引起错误的。


用指针输出字符串:C++不对数组的边界进行检测,但字符串有一个结束符’\0’(全0),在程序运行时是可以知道实际串长度的。cout<<ptr;将会直接输出"hello"


3. 字符串直接量作为基于栈的字符数组的初始值

    由于基于栈的变量不可能引用其他地方存储的内存,编译器会负责将字符串直接量复制到基于栈的数组内存中。

    例如: char stackArray[] = “hello”;

    做如下修改: stackArray[1] = ‘a’;是正确的。


4. 字符数组与字符指针

    字符数组的形式如下,会将字符直接量拷贝到栈上:

          char str[]   = "abc";             // 实际的数据存储: a b c \0,也就是增加了一个终结符\0

          char str[3] = {'a','b','c'};     // 实际的数据存储: a b c,并没有在最后添加终结符

          char str[10] = {'a','b','c'};   // 实际的数据存储: a b c \0 \0 \0 \0 \0 \0 \0

   字符指针的形式如下:

          char *str = “abc”;               // 实际的数据存储: a b c \0,也就是增加了一个终结符\0


5. 类型的决定

    1). 数组的类型是由该数组所存放元素的类型以及数组本身的大小决定的

         如char s1[3]和char s2[4],s1的类型就是char[3],s2的类型就是char[4],也就是说尽管s1和s2都是字符数组,但两者的类型却是不同的。

    2). 字符串常量的类型可以理解为相应字符常量数组的类型

         如"abcdef"的类型就可以看成是const char[7],也就是说实际的数据存储为"abcdef\0"。

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

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


总结字符指针和字符数组的不同之处:

(1)分配内存

设有定义字符型指针变量与字符数组的语句如下:
  char *pc ,str[100];
  则系统将为字符数组str分配100个字节的内存单元,用于存放100个字符。而系统只为指针变量pc分配4个存储单元,用于存放一个内存单元的地址。

字符指针可以使用malloc函数分配内存,而字符数组在定义时就已分配内存。

(2)初始化赋值含义
  字符数组与字符指针变量的初始化赋值形式相同,但其含义不同。例如:
  char str[ ] ="I am a student ! " ,s[200];
  char *pc="You are a student ! " ;
  对于字符数组,是将字符串放到为数组分配的存储空间去,而对于字符型指针变量,是先将字符串存放到内存,然后将存放字符串的内存起始地址送到指针变量pc中。
(3)赋值方式
  字符数组只能对其元素逐个赋值,而不能将字符串赋给字符数组名。对于字符指针变量,字符串地址可直接赋给字符指针变量。例如:
  str="I love China! "; //字符数组名str不能直接赋值,该语句是错误的。
  pc="I love China! "; //指针变量pc可以直接赋字符串地址,语句正确
(4)输入方式
  可以将字符串直接输入字符数组,而不能将字符串直接输入指针变量。但可将指针变量所指字符串直接输出。
  例如: cin >> str //正确
         cin >> pc //错误
         cout<<pc //正确
(5)值的改变
  在程序执行期间,字符数组名表示的起始地址是不能改变的,而指针变量的值是可以改变的。      例如:    str=str+5; //错误
 pc=str+5; //正确



对于sizeof与strlen: 

1. sizeof操作符的结果类型是size_t,它在头文件中typedef为unsigned int类型。该类型保证能容纳实现所建立的最大对象的字节大小。

2. sizeof是算符,strlen是函数。

3. sizeof可以用类型做参数,strlen只能用char*做参数,且必须是以''\0''结尾的。

4. 数组做sizeof的参数不退化,传递给strlen就退化为指针了。

5. 大部分编译程序在编译的时候就把sizeof计算过了,是类型或是变量的长度这就是sizeof(x)可以用来定义数组维数的原因。 
    char str[20]="0123456789"; // str是编译期大小已经固定的数组 
     int a=strlen(str); //  a=10; //strlen()在运行起确定,计算的是实际长度 
     int b=sizeof(str); //  而b=20; //sizeof()在编译期确定,str的类型是int[20],计算的是占据内存的大小

6. strlen的结果要在运行的时候才能计算出来,是用来计算字符串的实际长度,不是类型占内存的大小。

7. sizeof后如果是类型必须加括弧,如果是变量名可以不加括弧。这是因为sizeof是个操作符不是个函数。 
    char c; 
    sizeof c;  //变量名可以不加括弧 
8. 当适用于一个结构类型或变量, sizeof 返回实际的大小, 
    当适用一静态地空间数组, sizeof 归还全部数组的尺寸。 
    sizeof 操作符不能返回动态地被分派了的数组或外部的数组的尺寸


sizeof、strlen计算字符数组、字符指针空间

char str[] = "abc";  实际的数据存储: a b c \0,也就是增加了一个终结符\0 其类型为char[4]   VS: sizeof(str)=4     strlen(str) = 3 
GCC: sizeof(str)=4     strlen(str) = 3
const char str[]   = "abc"; 实际的数据存储: a b c \0,也就是增加了一个终结符\0 其类型为char[4]   VS: sizeof(str)=4     strlen(str) = 3 
GCC: sizeof(str)=4     strlen(str) = 3
char str[] = {'a','b','c'}; 实际的数据存储: a b c,并没有在最后添加终结符 其类型为char[3]   VS: sizeof(str)=3    strlen(str) = 15 
GCC: sizeof(str)=3    strlen(str) = 6
char str[3] = {'a','b','c'}; 实际的数据存储: a b c,并没有在最后添加终结符 其类型为char[3]   VS: sizeof(str)=3    strlen(str) = 15 
GCC: sizeof(str)=3    strlen(str) = 6
char str[5] = {'a','b','c','d','e'};  实际的数据存储: a b c d e ,并没有在最后添加终结符 其类型为char[5]   VS: sizeof(str)=5    strlen(str) = 19 
GCC: sizeof(str)=5     strlen(str) = 8
char str[5] = {'a','b','c','d'}; 实际的数据存储: a b c d \0(默认填充字符\0) 其类型为char[5]   VS: sizeof(str)=5     strlen(str) = 4 
GCC: sizeof(str)=5     strlen(str) = 4
char *pstr = "abcde"; 实际的数据存储: a b c d e \0 pstr的类型为char* sizeof(pstr) = 4 ( 指针的数据存储空间,4个字节),strlen(pstr) = 5

总结一下:

1). sizeof的结果是类型的大小,区分类型之后,sizeof的结果也就确定了,sizeof的结果是在编译期决定的,计算的占据的内存大小。

     srelen的结果是在运行期间决定,计算的是实际长度,strlen只能以char*作参数,以\0作为结束符, 以上的例子中,红色部分的strlen计算是错误的,

     因为在str的数据存储中并没有 一个\0字符,所以strlen的结果看似有点异常。

2). 注意在计算sizeof的时候:

     char str[] = "abc";  类型为char[4],   sizeof(str) = 4*sizeof(char) = 4.

3). sizeof(express),其中的express在编译过程中是不会被编译的,而是被替代类型。

     例如: int a = 1; sizeof(a=2);

     此时的express为a=2,在编译过程中被替换为sizeof(int),所以在执行完之后,a仍然是等于1.

4). 对函数使用sizeof,在编译阶段会被替换为函数的返回值的类型取代

     例如: int f(){return 0;}  sizeof(f());的结果为4.

             void f(){}            sizeof(f());编译过程中会出现错误,替换之后的sizoeof(void)编译无法通过.



这篇关于C++字符数组、字符指针、strlen、sizeof总结的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/957023

相关文章

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

【C++ Primer Plus习题】13.4

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: main.cpp #include <iostream>#include "port.h"int main() {Port p1;Port p2("Abc", "Bcc", 30);std::cout <<

hdu2241(二分+合并数组)

题意:判断是否存在a+b+c = x,a,b,c分别属于集合A,B,C 如果用暴力会超时,所以这里用到了数组合并,将b,c数组合并成d,d数组存的是b,c数组元素的和,然后对d数组进行二分就可以了 代码如下(附注释): #include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<que

C++包装器

包装器 在 C++ 中,“包装器”通常指的是一种设计模式或编程技巧,用于封装其他代码或对象,使其更易于使用、管理或扩展。包装器的概念在编程中非常普遍,可以用于函数、类、库等多个方面。下面是几个常见的 “包装器” 类型: 1. 函数包装器 函数包装器用于封装一个或多个函数,使其接口更统一或更便于调用。例如,std::function 是一个通用的函数包装器,它可以存储任意可调用对象(函数、函数

C++11第三弹:lambda表达式 | 新的类功能 | 模板的可变参数

🌈个人主页: 南桥几晴秋 🌈C++专栏: 南桥谈C++ 🌈C语言专栏: C语言学习系列 🌈Linux学习专栏: 南桥谈Linux 🌈数据结构学习专栏: 数据结构杂谈 🌈数据库学习专栏: 南桥谈MySQL 🌈Qt学习专栏: 南桥谈Qt 🌈菜鸡代码练习: 练习随想记录 🌈git学习: 南桥谈Git 🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈�

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

06 C++Lambda表达式

lambda表达式的定义 没有显式模版形参的lambda表达式 [捕获] 前属性 (形参列表) 说明符 异常 后属性 尾随类型 约束 {函数体} 有显式模版形参的lambda表达式 [捕获] <模版形参> 模版约束 前属性 (形参列表) 说明符 异常 后属性 尾随类型 约束 {函数体} 含义 捕获:包含零个或者多个捕获符的逗号分隔列表 模板形参:用于泛型lambda提供个模板形参的名

hdu 1166 敌兵布阵(树状数组 or 线段树)

题意是求一个线段的和,在线段上可以进行加减的修改。 树状数组的模板题。 代码: #include <stdio.h>#include <string.h>const int maxn = 50000 + 1;int c[maxn];int n;int lowbit(int x){return x & -x;}void add(int x, int num){while

git使用的说明总结

Git使用说明 下载安装(下载地址) macOS: Git - Downloading macOS Windows: Git - Downloading Windows Linux/Unix: Git (git-scm.com) 创建新仓库 本地创建新仓库:创建新文件夹,进入文件夹目录,执行指令 git init ,用以创建新的git 克隆仓库 执行指令用以创建一个本地仓库的