字符串在内存中的存储——C语言进阶

字符串是以ASCII字符NUL结尾的字符序列。ASCII字符NUL表示为\0.字符串通常存储在数组或者从堆上分配的内存中。不过,并非所有的字符数组都是字符串,字符数组可能没有NUL字符。字符数组也用来表示布尔值等小的整数单元,以节省内存空间。

C中有两种类型的字符串:

单字节字符串

由char数据类型组成的序列

宽字符串

由wchar_t数据类型组成的序列

wchar_t数据类型用来表示宽字符,要么是16位宽,要么是32位宽。这两种字符串都以NUL结尾。可以在string.h中找到单字节字符串函数,而在wchar.h中找到宽字符串函数。宽字符主要用于非拉丁字符集,对于支持外语的应用程序很有用,

字符串的长度是字符串中除了NUL字符外的字符数。为字符串分配内存的时候,要记住为所有的字符加上NUL字符分配足够的空间。

NULL和NUL不一样。NULL用来表示特殊的指针,通常定义为((void*)0),而NUL是一个char,定义为\0,两者不能混用!

字符常量是单引号引起来的字符序列。字符常量通常由一个字符组成,也可以包含多个字符,比如转义字符。在C中,它们的类型是int,如下所示:

printf("%d\n",sizeof(char));
printf("%d\n",sizeof('A'));

//output
//1
//4

字符串声明

声明字符串的方法有三种:字面量,字符数组,和字符指针。

字符串字面量是用双引号引起来的字符序列,常用来进行初始化,他们位于字符串字面量池中。<span style="color:#ff0000;">这和单引号引起来的字符不一样!</span>

下面是一个字符数组的例子:

char header[32];

下面是字符指针:

char *header;

字符串字面量池

定义字符量通常会将其分配到字面量池中,这个内存区域保存了组成字符串的字符序列。多次会用到同一个字面量时,字面量池通常会只有一个副本。这样可以减少应用程序占用的内存。通常认为字面量是不可变的,因此只有一份副本不会有什么问题。

字符串字面量一般分配在只读区域中,所以是不可变的。字符串字面量在哪里使用,或者他是全局,静态或者局部都无所谓,从这个角度讲,字符串字面量不存在作用域的概念。

在大部分编译器中,我们将字符串字面量看做常量,无法修改字符串。但是GCC编译器容许字符串字面量可以修改。

char *header = "Sound";
*header = 'L';
printf("%s\n",header);

//output
//Lound

这样就会改变字符串,不是我们预期的结果。因此应该避免这样做。像下面这样把变量声明为常量可以解决一部分问题。任何修改都会造成编译时错误:

const char *header = "Sound";

字符串初始化

初始化字符串采用的方法取决于变量是被声明为字符数组还是字符指针,字符串所用的内存要么是指针指向的一块内存。我们都可以用字符串字面量或者一些列字符初始化字符串,或者从别的地方(标准输入)得到字符。

初始化char数组

我们可以用初始化操作符初始化char数组。在下例中,header数组被初始化为字符串字面量中所包含的字符:

char header[] = "Media Player";

字符量"Media Player"的长度为12,表示这个字面量需要13个字节,我们就要为数组分配13个字节来持有字符串。初始化操作会把这些字符复制到数组中,以NUL结尾。

我们也可以用strcpy函数来初始化数组。

初始化char指针

用动态内存分配来初始化char指针。

char *header;
char *header = (char*)malloc(strlen("Media Player")+1);

注意不要用sizeof操作符,而要用strlen函数来确定已有字符串的长度,sizeo操作符会返回数组和指针的长度,而不是字符串的长度。

字符串在内存中的存储——C语言进阶

时间: 2024-08-05 01:53:59

字符串在内存中的存储——C语言进阶的相关文章

QList介绍(QList比QVector更快,这是由它们在内存中的存储方式决定的。QStringList是在QList的基础上针对字符串提供额外的函数。at()操作比操作符[]更快,因为它不需要深度复制)非常实用

FROM:http://apps.hi.baidu.com/share/detail/33517814 今天做项目时,需要用到QList来存储一组点.为此,我对QList类的说明进行了如下翻译. QList是一种表示链表的模板类.QList<T>是Qt的一种泛型容器类.它以链表方式存储一组值,并能对这组数据进行快速索引,还提供了快速插入和删除等操作.QList.QLinkedList和QVector提供的操作极其相似:* 对大多数操作来说,我们用QList就可以了.其API是基于索引(inde

C语言中浮点数在内存中的存储方式

关于多字节数据类型在内存中的存储问题 //////////////////////////////////////////////////////////////// int ,short 各自是4.2字节.他们在内存中的存储方式以下举个样例说明. int data = 0xf4f3f2f1; 当中低位存放在编址小的内存单元.高位存放在编址高的内存单元 例如以下: 地址:0x8000      0x8001    0x8002   0x8003 数据:   f1              f2 

移码及浮点数在内存中的存储方式

首先说一下十进制的小数怎么转化为二进制的小数,计算机根本就不认识10进制的数据,他只认识0和1,所以,10进制的小数在计算机中是用二进制的小数表示的. 十进制的小数转化为二进制的小数的方法: 可以简单的概括为正序取整,将十进制的小数部分乘以2,然后取整数部分. 例如将0.2转化为二进制的小数,那么0.2*2=0.4,其整数部分是0,所以二进制小数的第一位为0,然后0.4*2=0.8,其整数部分是0,所以二进制小数的第二位为0,然后0.8*2=1.6,其整数部分是1,所以二进制小数的第三位是1,然

变量在内存中的存储方式-----“大端”和“小端”

"大端"和"小端"可以追溯到1726年的Jonathan Swift的<格列佛游记>,其中一篇讲到有两个国家因为吃鸡蛋究竟是先打破较大的一端还是先打破较小的一端而争执不休,甚至爆发了战争.1981年10月,Danny Cohen的文章<论圣战以及对和平的祈祷>(On holy wars and a plea for peace)将这一对词语引入了计算机界(<程序设计实践>第9章).这么看来,所谓大端和小端,也就是big-endia

float 在内存中如何存储的

float类型数字在计算机中用4个字节存储.遵循IEEE-754格式标准:    一个浮点数有2部分组成:底数m和指数e 底数部分 使用二进制数来表示此浮点数的实际值指数部分 占用8bit的二进制数,可表示数值范围为0-255 但是指数可正可负,所以,IEEE规定,此处算出的次方必须减去127才是真正的指数.    所以,float类型的指数可从-126到128 底数部分实际是占用24bit的一个值,但是最高位始终为1,所以,最高位省去不存储,在存储中占23bit    科学计数法. 格式:SE

浮点数在内存中的存储(简述)

数据类型: 1.基本类型(整形,浮点型,字符型) 2.构造类型(数组,结构体,联合,枚举) 3.指针类型 查看数据范围:整形范围(limits.h) 浮点型类型(flaot.h) eg:有符号的char的表示范围:0000 0000~1111 1111(-128~127)其中最高位表示符号位,0为正 1为负 其实数据的存储和访问就下像作图这个圈一样,当你给它的127+1它就会变成128 整形变量: 一般来说字长为32的情况下,整形表示32位,短整形16位,长整形32位 数据在计算机中以补码的形式

一个 -100.01 的double 在内存中怎么存储的. 一个中文String 在内存中占多少直接 utf-8 / GBK

一.-100.01 的double 在内存中怎么存储的 double双精度数据类型存储格式IEEE 双精度格式为8字节64位,由三个字段组成:52 位小数 f : 11 位偏置指数 e :以及 1 位符号 s.这些字段连续存储在两个 32 位字中 二.一个中文String 在内存中占多少直接 utf-8 / GBK [腾讯实习生问到这个问题,当时还天真的回答unicode字符集和16位,哎...] GBK:1个ASCII码占1个字节,而1个汉字编码占2个字节. UTF:ASCII对应的字符在UT

结构体在内存中的存储方式

结构体在内存中如何存储? 遵循结构体对齐规则: 1.首先要知道默认对齐数:VS 中 8   Linux 中4 2.第一个成员放到0偏移处 3.后面所有的成员都放到对齐数(本身和默认对齐数的较小值)的倍数处偏移 4.结构体总大小为所有对齐数中最大对齐数的倍数 Eg: 运行结果为 24 图中可以看出内存有浪费,而我们将小的成员放一起可以节省资源 减少浪费. 上例可以改为: int i: char c: double d: 这样总大小只需16 节省浪费. 空的结构体类型大小为1,创建对象需要开辟空间,

Java对象在内存中的存储

Java对象在内存中的存储分3块区域 1.对象头(Header) 2.实例数据(Instance Data) 3.对齐填充(Padding) 一.对象头 哈希码.GC分代年龄.锁状态标志.线程持有的锁.偏向线程ID.偏向时间戳 类型指针 二.实例数据 各种类型的字段(父类继承下来的.子类自身定义的) 相同宽度的字段会被分配到一起 三.对齐填充 没有特别含义,仅仅起着占位符的作用(8字节的整数倍)