C语言参悟-数据类型

这篇具有很好参考价值的文章主要介绍了C语言参悟-数据类型。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、概述

编程语言为抽象这个物理世界提供了依据,其中对于描述物理世界的情况提供了一个叫做数据类型的名字,这种数据类型是我们人类能够认识的东西,就像数字,字母,字符之类的。

C语言中也提供了数据类型这种说法,就像下面的图片里面猴子,我们用C语言描述图片里面的猴子,就可以用 C语言里面的 字符串 数据类型来描述:

char * imageDescription = "两只猴子,一个大猴子,一个小猴子";

C语言参悟-数据类型,▼ C/C++  参悟笔记,c语言,开发语言,c数据类型
下面是我对 C语言里面的数据类型的理解使用参悟。

二、基础数据类型

1. 整数

C语言里面的整数类型标识符就是:int, long, long longshort,就行 0,-1,-23,4235 等等,也就是不带小数的整数。最常用的是 int。 long, long long适合大场景的整数 ,相对于整数只是存的数值范围比较大而已,属性基本一致,后面我都是用int来举例代表整数的。short 就是使用时相对较小的索引范围值而已。在后面会有一个专门的表去归纳这些变量的内存模型。

C语言里面的整数用处很多,因为计算内部都是用二进制表示数据的,里面的数据本质上都是整数的,浮点数也是用二进制整数去描述的。整数有很多的性质都十分有用,比如整数除法的结果也是整数等等。整数在计算之外的最大用处就是索引,在数组、循环、判断、地址索引等场景都是用的整数去做的。

1. 计算

声明一个 int 变量也很简单的,直接是 int 变量名;如果没初始化默认是给的一个随机值,一定要记得初始化哈。因为在像循环的时候,总是得从一个有效的开始索引进行索引,如果没设置好值,这就会出问题,就会出现段错误。

C语言整数一个很有用的计算就是 除法, 而且 取余 运算只能 整数 哦

就像下面,除法会把除出来的数的小数部分给抛掉,只保留整数部分

// 声明变量并初始化,初始化就使用 = 
int i = 0;

i = 1 / 2;	//i = 0

取余 运算也是很简单的

int i = 11;

i = i / 2;	//i = 0

对应 最经典便是 个十百位

#include <stdio.h>

int main()
{
    int numA, numB, numC, numD;
    printf("请输入一个三位数: ");
    scanf("%d", &numA);
    numA = (int)numA;
    numD = numA % 10;
    numC = (numA / 10) % 10;
    numB = numA / 100;
    printf("这个三位数的个十百分别为:%d %d %d",numD, numC, numB);
    return 0;
}

2. 索引

数组的本质其实就是一个数据表,一维数组就是单行表,二维数组就是多行表,整数在索引的时候其实就可以当一个表示位置的强大工具。

就像下面的一个二维数据表就是用的 行 - 列 来确定位置的,这里用浮点数明显就是不行的。

表[ 行索引 ][ 列索引 ] 来确定一个位置的值
C语言参悟-数据类型,▼ C/C++  参悟笔记,c语言,开发语言,c数据类型

int martx[3][3] = {{0, 1, 2}, {4, 5, 6}, {7, 8, 9}};

对于上面的 martx 数组, 我们要取得 第 2 行,第 1 列的数据就是使用 martx[1][0]

最灵活的莫过于 对这个 索引 的变化。

2. 浮点数

浮点数其实就是 小数,对了科学计数法的写法也是浮点数类型哈。

在C语言里面的 浮点数的类型就是 float, double 两个类型,其实就是一个精度低,精度高的区别,一般使用double的多些。

对于这个的使用其实并不会太过多的考虑,但是要考虑到一个就是在 他和其他数据运算的时候,有他就会让数据的类型往浮点数靠

就像 7+7.32 的结果 就是浮点型
但 7+7 的结果就是 整型

3. 字符

C语言里面的字符主要是指英文字符,类型使用 char 表示。

声明就像下面的格式声明,用单引号来包括一个字符,这些字符全是 ASCII字符哈,也就是下面的 3,4 表格里面的所有值,其实char 也是一种特殊的int类型,他也是用的整数表达字符。

字符的比较大小其实也就是比较 对应 的 ASCII 的码值哈。

char 的大小就是 1个字节,刚好表示 128个数

char ch = 'A';

对应这个表格之外的字符就不是 ASCII 的编码了,那就不能用 char 来表示
就像下面表示中文字符就是不对的:

char  sc = '张';

中文字符是用的 Unicode 编码,就是两个字节,但char只有一个字节的大小,所以用不了,编译器就会对这个报错

那存储中文以及其他字符的话就得用 字符串去描述了。

3. 控制字符
ASCII控制字符的编号范围是0-31和127(0x00-0x1F和0x7F),共33个字符。
C语言参悟-数据类型,▼ C/C++  参悟笔记,c语言,开发语言,c数据类型
4. 可显示字符
可显示字符编号范围是32-126(0x20-0x7E),共95个字符。
C语言参悟-数据类型,▼ C/C++  参悟笔记,c语言,开发语言,c数据类型

4. 字符串

字符串本质上就是就是一种数据,是 一系列连续的字符构成的连续串,因为字符串这种数据类型在实际项目中使用的是非常多,因为这个是和人类的文字语言是最接近的一种格式,正如你所看到的内容便是 由字符构成的字符串数据。

因为存储的需要,指针和字符串是密不可分的,就需要把把指针和字符串结合起来一起看最好。

5. 指针

指针就是一个数据类型,专门存放其他变量的地址的一个类型。指针是一个很大内容,有兴趣可以看看我的笔记

指针入门基础
C的动态内存管理
指针与函数
指针和数组
指针与字符串

三、特殊数据类型

1. 枚举

枚举类型其实就是 一种为了简化编程命名的类型。用于定义一组具有离散值的常量。它可以让数据更简洁,更易读。

枚举类型通常用于为程序中的一组相关的常量选项取名字,以便于程序的可读性和维护性。

就像我们定义一组颜色的表示,可以用宏定义来做

#define 0 Red
#define 1 Green
#define 2 Blue
#define 3 Yellow

当然更推荐使用 枚举 来做,这样更好维护,下面一看就知道是Color里面的某个值,比较宏定义只是简单的替换,不会去检查值的正确性。但数据类型就不一样了,数据类型就会被严格的检查的。

就行下面的声明调用

enum Color
{
	Red,
	Green,
	Blue,
	Yellow
};

//声明一个变量,要带enum 关键字
enum Color m_color = Color.Red;

更推荐 搭配 typedef 一起使用

typedef enum Color
{
	Red,
	Green,
	Blue,
	Yellow
}CColor;

//声明一个变量
CColor m_color = CColor.Red;

当然,枚举类型也是有值的哈,而且是整数的,这就意味着可以用 switch 的方式去判断

默认从0开始,依次递增,就像Red 值是0,Green = 1, Blue = 2 等等。

如果手动设置值,那后面的值就在那个设置的值基础上自动加 1

当然也可以这样写

enum Color
{
	Red,
	Green = 4,
	Blue,
	Yellow
};

Red 默认从0开始,依次递增,因为Green 手动设置为值是4,那后面的依次递增 Blue = 5, Yellow = 6 等等。
这个属性知道就可以啦,不用强制明白。

2. 共用体

共用体是一种特殊的数据类型,可以在相同的内存位置存储不同的数据类型。但是数据在内存一个时间点里面只有一种类型哈

我们可以定义一个带有多成员的共用体,但是任何时候只能有一个成员带有值。

共用体提供了一种使用相同的内存位置的有效方式。

union Data
{
   int i;
   float f;
   char  str[20];
} ;

union Data m_Data;

我们也可以用typedef简化定义

typedef union Data
{
   int i;
   float f;
   char  str[20];
} Un_Data;

Un_Data m_Data;

现在,Data 类型的变量可以存储一个整数、一个浮点数,或者一个字符串。这意味着一个变量(相同的内存位置)可以存储多个多种类型的数据。我们可以根据需要在一个共用体内使用任何内置的或者用户自定义的数据类型

共用体占用的内存应足够存储共用体中最大的成员

就像上面的,Data 将占用 20 个字节的内存空间大小,不管存int, float 还是 char*;

2. struct结构体

struct结构体 C语言给我们提供的一个开放的定义自己的 数据类型 的一个强大工具,我们可以用 struct 去描述一个数据结构,在这个结构里面用的就是上面提到的数据类型,当然也是包括在结构体内再存结构体的。

举个例子:我们用一个结构体描述一个位于屏幕上的圆的数据。

这个圆有半径,圆有相对屏幕左上角坐标位置,圆还有外围圆的线宽,外围线的颜色,内圆的填充颜色等数据。

1. 定义结构体

struct 结构体名称{内部类型} ;

在使用的时候就是把 struct 结构体名称 当成一个自定义的类型使用就好,就像 int 一样的使用。

那定义一个这样的圆可以这么写

// 颜色结构体
struct color{
    short red;
    short green;
    short blue;
};

// 位置
struct point{
	int x;
	int y;
}

// circule
struct circule{
	int Radius;
	struct point Point;
	struct color OuterColor;
	struct color InnerColor;
}

但是这种写法可能有点夯长,那我们就可以用 typedef 来把这个结构体命名一样,命名成我们更加可读的 变量类型名称。

typedef 类型 自己想要的类型名

可以就把上面的代码改写一下

struct color{
    short red;
    short green;
    short blue;
};

//定义别名
typedef struct color ST_Color;

// 位置
struct point{
	int x;
	int y;
};

typedef struct point ST_Point;

// circule
struct circule{
	int Radius;
	ST_Point Point;
	ST_Color OuterColor;
	ST_Color InnerColor;
};

typedef struct circule ST_Circule;

当然我们还可以直接用 typedef 去简化定义,在什么结构体的时候就给命别名

typedef struct color{
    short red;
    short green;
    short blue;
} ST_Color;

2. 使用结构体

结构体的使用同样也是很简单的,就和普通的类型一样,只是在访问结构体内部成员的时候要用 ‘.’ 符号访问而已

下面我就声明一个圆形的结构体

// 声明结构体
ST_Circule m_circlue;
ST_Circule *p_circle = NULL;

// 初始化结构体
m_circlue.Radius = 10;
m_circlue.Point = {0,0};	//这种是是用列表初始化
m_circlue.InnerColor = {12,23,34};

m_circlue.OuterColor.blue = 12;	//这种是每个单独的去初试化
m_circlue.OuterColor.red = 23;
m_circlue.OuterColor.green = 34;

//在使用结构体指针的时候,为了区分是指针所有还是用的变量名索引,在访问结构体成员变量的时候会用 -> 来区分
p_circle = &m_circlue;
printf("m_circlue-Radius: %d", p_circle->Radius);

3. 内存布局
结构体内存大小理论上是和其内部所有成员内存大小之和。而且成员的内存排列顺序一定是定义顺序。

C语言参悟-数据类型,▼ C/C++  参悟笔记,c语言,开发语言,c数据类型

理论上讲结构体的各个成员在内存中是连续存放的,和数组非常类似,但是,结构体的占用内存的总大小不一定等于全部成员变量占用内存大小之和。在编译器的具体实现中,为了提高内存寻址的效率,各个成员之间可能会存在缝隙。

就像 ST_Circule 的理论大小是 24 字节。就是连续的。

在结构体里面其实是并非完全的内存连续,就是其实是有内存对齐的。

默认的字节对齐原则

首先引出一个概念自然对齐(naturally aligned),是指数据的起始地址是该数据类型大小的倍数。结构体的对齐是指其中的每个数据成员都是自然对齐的,要达到这个效果可能需要在成员之间进行必要的字节填充。比如一下struct:

struct Struct {
  char c1; // 1B
  uint64_t n1; // 8B
};

在默认情况下需要在c1后面填充7个字节,才能保证n1是自然对齐的。此时sizeof(DemoStruct)==16

C/C++ struct通常的对齐原则如下:
保序:
在保序的基础上保证每个成员是自然对齐的,如果前一个成员紧接着的地址不满足对齐要求,则增加填充。
最后一个成员后面也可能会增加填充,这样能保证创建struct数组时,数组中的每个struct仍然是对齐的。
结构体嵌套时,递归的按照结构体中最大的那个成员对齐。(注意不是最大的结构体,而是结构体总最大的那个成员

pragma pack(1)抹除填充

我们可以通过#pragma pack(1)来强制struct不增加填充,比如如下struct:

#pragma pack(1)
struct DemoPackStruct {
  char c1; // 1B
  uint64_t n1; // 8B
};

由于强制改成了1字节对齐,所以上述结构体中无需填充。此时sizeof(DemoPackStruct)==9。

这么做的主要目的就是节省内存,以损失访存效率为代价。可能还有一个作用是方便数据结构的网络传输,比如直接免去序列化过程将整个数据结构通过网络发送,但这么做并不保险,因为不同机器之间存在字节序的问题(大端/小端,endianness)。

当然也可以给指定更大的pack值,以强制struct按更大的字节对齐,比如以下数据结构 sizeof(DemoPack2Struct)==10:

#pragma pack(2)
struct DemoPack2Struct {
  char c1; // 1B
  uint64_t n1; // 8B
};

使用pack需要注意以下几点:

pack(n)的值必须是2的指数,比如n可以是1,2,4等

pack只能用于减少sturct的padding,不能用于增加padding。比如一个struct中最大的成员是8字节,那么pack(16)不起任何作用。

#pragma pack()影响这条语句之后的所有struct声明,可通过pack(push), pack(pop)保存和恢复之前默认的pack文章来源地址https://www.toymoban.com/news/detail-629641.html

四、数据类型修饰符

1. const

2. unsigned、signed

到了这里,关于C语言参悟-数据类型的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 以太坊智能合约开发:Solidity 语言中的数据类型

    本文我们介绍Solidity语言的数据类型,重点是值类型,包括布尔类型、整型、地址类型、字节类型、字符串类型和枚举类型。并且通过两个智能合约例子,用于演示这些数据类型的声明与使用方法。 访问 Github 仓库 获取更多资料。 Solidity中关于数据类型的定义如下: Solidity是

    2024年02月02日
    浏览(67)
  • C语言——自定义类型结构体_学习笔记

    结构体是一种用户自定义的数据类型,可以包含 多个不同类型的变量 。通过使用结构体,我们可以将相关联的数据组织在一起,便于管理和使用。 在C语言中,结构体(struct)指的是一种数据结构,是C语言中聚合数据类型的一类。 结构体可以包含多个不同类型的数据成员,例

    2024年02月07日
    浏览(38)
  • [学习笔记]解决因C#8.0的语言特性导致EFCore实体类型映射的错误

    今天下午在排查一个EF问题时,遇到了个很隐蔽的坑,特此记录。 使用ef执行Insert对象到某表时报错,此对象的Address为空: 检查数据库和迁移文件时发现Address这个字段被意外设置成 nullable: false ,而其它的字段却正常,按理来说对于string类型的属性,EFCore在codefirst模式下应该

    2024年02月05日
    浏览(35)
  • C语言——数据类型

    变量就是在程序中可以发生变化的量,变量有类型。 变量的类型决定了变量存储占用的空间,以及如何解释存储的位模式。(1字节=8位) 例如:(auto) int a; 变量名是标识符,要符合标识符命名规则。 存储类型:变量存储的位置。 数据类型包含:名字 字节 取值范围 类型 存储大

    2024年02月04日
    浏览(22)
  • Go 语言基本数据类型

    Go 语言中数据类型分为:基本数据类型和复合数据类型 基本数据类型有: 整型、浮点型、布尔型、字符串 复合数据类型有: 数组、切片、结构体、函数、map、通道(channel)、接口等。 整型分为以下两个大类: 有符号整型按长度分为:int8、int16、int32、int64 对应的无符号整

    2024年01月22日
    浏览(59)
  • [go语言]数据类型

    目录 知识结构 整型、浮点型 1.整型 2.浮点型 复数、布尔类型 1.复数 2.布尔类型 字符与字符串 1.字符串的格式化 2.字符串的截取 3.格式化好的字符串赋值给量 4.字符串的转换 5.strings包 在Go语言中,整型数据是一种基本的数据类型,用于表示整数。Go语言提供了多种整型数据类

    2024年01月19日
    浏览(49)
  • 【C语言----数据类型】

    提示:本篇文章为C语言数据类型的个人总结,内容如若有误,请及时联系我更正。 如若转载请注明原创,谢谢。 大家好,我是小明,很抱歉由于个人原因断更了一段时间,从今天开始恢复正常更新,今天总结的是C语言数据类型相关知识。 提示:以下是本篇文章正文内容:

    2024年02月12日
    浏览(25)
  • R语言01-数据类型

    数值型(Numeric):用于存储数值数据,包括整数和浮点数。例如:x - 5。 字符型(Character):用于存储文本数据,以单引号或双引号括起来。例如:name - “John”。 逻辑型(Logical):用于存储布尔值,即TRUE或FALSE。用于表示逻辑条件的真假。例如:is_student - TRUE。 因子型(

    2024年02月11日
    浏览(26)
  • C语言-数据类型

    数据类型 中文名称 空间大小(bite - 字节) char 字符串数据类 1 short (int) 短整型 2 int 整形 4 long 长整形 4 long long 更长的整形 8 float 单精度浮点数 4 double 双精度浮点数 8 sizeof() - -操作符 - 计算类型或者变量所占空间的大小 单位是字节byte 计算大小以节省空间 bit - 比特位 计

    2024年02月08日
    浏览(30)
  • 01- 数据类型(C语言)

    1、在我们所写的“第一个C程序”中出现了很多的标识符,例如 include 、 main 、 printf 、 return 。标识符是⽤来标识 变量 、 函数 ,或任何其他⽤户 ⾃定义项⽬的名称 。 2、标识符的约束规范: 只能包含 数字、字母 和 下划线 不能以数字开头 区分大小写 1. 当我们在使用C语言

    2024年02月09日
    浏览(30)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包