全面理清概念,C风格字符串(多重定义方式,区别,易错点)-程序员宅基地

技术标签: c++  c语言  C/C++基础知识  

C风格字符串

C风格字符串是一种在C语言中表示字符串的方式,它是通过字符数组来实现的。

  • C风格字符串是一系列字符,以空字符(‘\0’)作为结束标志。这意味着在声明并定义一个C风格字符串时,我们需要为数组分配比实际字符串长度多一个元素的空间,以存放空字符

C风格字符串的定义

C风格字符串的定义和写法:

  • 字符数组方式定义C风格字符串

    char str[] = "Hello, World!";
    
    • 编译器会自动计算字符串长度,并为字符数组分配适当的空间(包括空字符)。

    • 这个例子中,str 是一个包含14个字符的数组,包括13个实际字符和1个空字符。

    • 或者,向下面这样定义:

    char str[14] = "Hello, World!";
    
  • 指针方式定义C风格字符串

    char *str = "Hello, World!";
    
    • 这种写法的注意事项:

      • str 是一个指针,它指向一个字符串常量。因此,尽管你可以更改指针指向的位置,但不能通过指针来更改字符串内容。

      • 试图修改字符串常量的内容可能导致未定义的行为。

      • str[0] = 'h'; // 错误!不能修改字符串常量的内容

      • 在使用这种写法时,字符串的长度不需要显式指定。编译器会自动计算字符串长度,并在末尾添加空字符。

      • 与字符数组相比,这种写法使用的内存可能更少,因为字符串常量可能存储在只读内存区域,并且在程序中多次使用相同的字符串常量时,编译器可能会将它们合并为一个实例。

  • 小小总结一下两种定义的区别

    • 使用字符数组形式创建的C风格字符串,可以使用str[0] = 'h';这样的形式,去修改字符数组中的字符。
    • 使用字符指针的形式创建的C风格字符串,不可以使用str[0] = 'h';这样的形式,去修改字符数组中的字符,会导致未定义的行为!

C风格字符串的易错点

  • 未给字符串分配足够的空间以存放结尾的空字符,可能导致内存溢出、程序崩溃等问题。
  • 在处理C风格字符串时,很容易遗漏字符串末尾的空字符,从而导致未定义的行为。
  • 在字符串操作过程中,如果不小心修改了空字符,可能导致字符串操作函数无法识别字符串的终止位置。

C风格字符串与普通字符串的区别

  • C风格字符串实际上是一个字符数组,其表示形式为以空字符结尾的字符序列。
  • 普通字符串通常指C++中的std::string类型,它是一个类,封装了很多便捷的字符串操作函数,使用起来更加方便。
  • C风格字符串在内存中是连续的字符,以空字符结尾。普通字符串不一定以空字符结尾,因为std::string会自动处理字符串长度和结尾问题。
  • C风格字符串的操作需要更多的手动处理和注意事项,而std::string提供了许多内置函数来简化字符串操作。

C风格字符串用于判断大小时

  • 使用strlen()函数,返回的字符串长度不包括结尾的空字符。这是因为strlen()函数遍历字符串时以空字符作为结束条件,因此计算的长度不包括空字符。
#include <string.h>

char str[] = "Hello, World!";
size_t len = strlen(str);  // 返回13,不包括空字符
  • 若要获取包括空字符在内的字符串大小,可以使用sizeof()函数。sizeof()函数返回的是整个字符数组的大小,包括空字符。
char str[] = "Hello, World!";
size_t size = sizeof(str);  // 返回14,包括空字符

又发现一个不容易发现的易错点。(必看)

今天在使用memcpy函数的时候发现了一个错误。
memcpy的函数原型如下:

void *memcpy(void *dest, const void *src, size_t n);
参数说明:
dest:目标内存区域的指针,即复制数据的目的地。
src:源内存区域的指针,即要复制的数据来源。
n:要复制的字节数(数据大小)。
  • 我在将一个C风格字符串复制到一个共享内存段的过程中,不是要指定第三个参数嘛,第三个参数是一个数字。
  • 我的C风格字符串是这样写的 char * str = "hell0, world!" ,然后我的第三个参数是这么指定的sizeof(str);
  • 大家知道我错哪里了吗?
  • sizeof运算符用于计算一个变量或类型所占用的字节数。
    • 当你使用sizeof(str)时,你实际上计算的是指针变量str的大小,而不是指向的字符串的长度。
    • 因为str是一个指针变量,所以sizeof(str)通常返回指针变量的大小(在32位系统中通常为4字节,64位系统中通常为8字节),而不是字符串的实际长度。
  • 对我就错这里了,真是坑爹。
  • 假如说我C风格字符串是这么写的 char str[] = "hell0, world!",那我就可以使用sizeof函数去计算数组的数量。
  • 如果我的C风格字符串是字符指针类型的,那么我这里就只能使用strlen(str) + 1,来指定第三个字符的大小。

是不是觉得C风格字符串超容易错!!!!!

总结

  • 在C和C++程序中,C风格字符串的表现和实现基本相同。C风格字符串在两种编程语言中都是通过字符数组实现的,以空字符(‘\0’)作为结束标志。无论是在C还是在C++中,对C风格字符串的操作和处理方式是一致的。

  • 然而,需要注意的是,虽然C风格字符串在C和C++中的表示和实现相同,但C++提供了更高级的字符串类型,即std::string。std::string是一个封装了很多便捷字符串操作的类,使用起来更加方便。当在C++中编写程序时,建议使用std::string而不是C风格字符串,以便利用其提供的高级功能并避免一些潜在的风险。

  • 在C++这门语言中,C风格字符串与普通字符串的最大区别是,C风格的字符串是以空字符(‘\0’)结尾的。这只是一种特别的书写习惯,并是不一种额外的数据类型。

尽管C++中支持使用C风格字符串,但是在C++程序中最好还是不要使用它们。这是因为C风格字符串不仅仅使用起来不太方便,而且极易引发程序漏洞,是诸多安全问题的根本原因!!!

最后的最后,如果你觉得我的这篇文章写的不错的话,请给我一个赞与收藏,关注我,我会继续给大家带来更多更优质的干货内容

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_49503250/article/details/130602662

智能推荐

org.apache.commons.codec.binary.Base64 加密解密_org/apache/commons/codec/binary/base64-程序员宅基地

文章浏览阅读1.8w次,点赞3次,收藏5次。使用Apache的org.apache.commons.codec.binary.Base64类完成Base64加密解密_org/apache/commons/codec/binary/base64

spring项目中使用alibaba.druid.pool.DruidDataSource来装载oracle数据源-程序员宅基地

文章浏览阅读1.3k次。0、编写配置文件jdbc.type=oraclejdbc.driver=oracle.jdbc.driver.OracleDriverjdbc.url=jdbc:oracle:thin:@192.168.2.9:1521/orcljdbc.username=xbsjdbc.password=xbs1、spring-context.xml中装载配置文件..._com.alibaba.druid.pool.druiddatasource 连接oracle 配置

base64在html页面显示图片的方式_qdhph0930b.xyz-程序员宅基地

文章浏览阅读4.6w次。<img src='data:image/png;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAIBAQEBAQIBAQECAgICAgQDAgICAgUEBAMEBgUGBgYFBgYGBwkIBgcJBwYGCAsICQoKCgoKBggLDAsKDAkKCgr/2wBDAQICAgICAgUDAwUKBwYHCgoKCgoKCgoKCgoKCgo..._qdhph0930b.xyz

多线程-程序员宅基地

文章浏览阅读97次。多线程Java.Thread进程和线程关系及区别1.定义进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位.线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.2.关系一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行.相对进

友盟自动集成报错-Could not download common (com.umeng.umsdk:common:2.0.0)_could not find com.umeng.umsdk:common:2.0.2.-程序员宅基地

文章浏览阅读1.2w次。当使用自动集成(非手动集成)友盟的时候在build.gradle里面:implementation 'com.umeng.umsdk:analytics:8.0.0'implementation 'com.umeng.umsdk:common:2.0.0'但是今天一直报错Could not download common (com.umeng.umsdk:common:2.0.0)..._could not find com.umeng.umsdk:common:2.0.2.

Docker 快速上手学习入门教程_docker菜鸟教程-程序员宅基地

文章浏览阅读2.5w次,点赞6次,收藏50次。官方解释是,docker 容器是机器上的沙盒进程,它与主机上的所有其他进程隔离。所以容器只是操作系统中被隔离开来的一个进程,所谓的容器化,其实也只是对操作系统进行欺骗的一种语法糖。_docker菜鸟教程

随便推点

【Java算法】AES前端加解密,Java后端加解密,采用CBC模式_aes-cbc前后端如何共享iv-程序员宅基地

文章浏览阅读1.4k次,点赞11次,收藏11次。适用范围:1、前端加密、解密2、后端加密、解密3、前端加密、后端解密4、后端加密、前端解密前端AESimport CryptoJS from 'crypto-js'import moment from 'moment'let key = CryptoJS.enc.Utf8.parse('abcdefg123456789') // key:必须16个字符let iv = CryptoJS.enc.Utf8.parse('abcdefg123456789'); // 偏移量:必须16个字符_aes-cbc前后端如何共享iv

oracle哈希检查数据一致性,数据文件SCN的一致性问题-程序员宅基地

文章浏览阅读110次。数据文件SCN的一致性问题1、数据库正常运行中,所有数据文件的SCN都是一致的吗?2、将一数据文件offline后,再将其online时,这个数据文件的SCN会前提吗?假如是,前提到的SCN是怎么确定的?1.数据库正常运行时,所有数据文件的SCN不一定一致。问题在这个所有上,比如Offline表空间,数据文件的SCN会被冻结,而且表空间的数据文件offline/online时又会发生文件检查点,使..._oracle 查看scn号是否一致

java cacti_cacti监控安装-程序员宅基地

文章浏览阅读115次。cacti是用PHP实现的一个软件,它用snmp服务获取数据,然后用rrdtool存储和更新数据,并生成图表展示。比较适合用于交换机、路由器的网络监控,插件众多,可图示化显示网络状况。cacti官方推荐版本如下:PHP 5.4+MySQL 5.1+RRDtool 1.3+, 1.5+ recommendedNET-SNMP 5.5+Web Server with PHP support cento..._cacti哪个版本好用

联邦学习综述-程序员宅基地

文章浏览阅读302次。联邦学习_联邦学习综述

virtuoso--工艺库答疑_tsmc mac-程序员宅基地

文章浏览阅读436次。一种带nbl_mac,一种带iso_mac?从版图结构上来看,iso_mac的管子自带bulk绕一圈,有HVNW电位,最外围加上P+ isolation。3. 有了tt, ss, ff, sf, fs后,为何既有mc lib 又有 mismatch lib?--尽量用带mac的lib。_tsmc mac

C++中的exit函数_c++ exit-程序员宅基地

文章浏览阅读6.9k次,点赞13次,收藏37次。**描述:**用来立即中止当前程序的执行,并将一个整数返回给系统,该整数的作用与“由mian函数返回的整数”相同,如果是0表示程序正常退出;如果非0表示程序异常退出。头文件#include<cstdlib>使用exit(0);//程序正常退出exit(1)//程序异常退出..._c++ exit