首页 > 其他分享 >C语言数据类型及存储

C语言数据类型及存储

时间:2024-09-27 18:23:18浏览次数:11  
标签:存储 struct int 数据类型 C语言 pe 类型 对齐 定义

C语言数据类型分类

C语言数据类型分为内置类型和自定义类型

内置类型

内置类型是C语言自带的数据类型,整形,浮点型,字符型,指针,空类型等都属于内置类型,他们的意义比较单一,往往用来表示一个含义,比如整形,可以用来记录年龄,次数等数据,浮点类型可以用来存放身高,成绩等实数类型。

void(空类型)不做变量的定义,他的作用大部分场景在函数返回值类型(可以参考C语言函数),还有部分场景会使用到void*的指针。
他们在C语言中可以如下表示

int         //整形数据类型
short int   //短整型数据类型
char        //字符型数据类型
int*        //整形指针数据类型
double      //双精度浮点型
float       //单精度浮点型
void        //空类型

自定义类型

自定义类型是描述复杂的含义,用单一的内置类型无法描述时,所使用的类型,是由用户自己来定义的,通俗一点说就是DIY。

结构体类型

我们需要描述一个人,他有身高,有体重,有性别,有年龄,用单纯的int或者char无法全部描述,因此我们可以进行如下操作

#include<stdio.h>
#include<string.h>
struct people{   //"struct people"为我们自定义的类型,下列name,height等成为成员变量
   //下列name,height等成为成员变量   
     char name[10]; //姓名
     float height;  //身高
     float weight;  //体重
     char sex;      //性别
     int age;       //年龄
};//声明结构体类型


int main()
{
    struct people pe; //定义结构体,
   //为其成员变量赋值
     strcpy(pe.name,"张三");  //字符串拷贝
     pe.height = 183.5;
     pe.weight = 130.5;
     pe.sex = 'm';
     pe.age= 18;
   //打印信息
   printf("姓名:%s 身高:%f 体重:%f 性别:%c 年龄:%d",pe.name,pe.height,pe.weight,pe.sex,pe.age);
    return 0;
}   

结构体类型可以将内置类型和自定义类型组合,构成一个类型,访问其成员时,可以进行如下操作

struct people pe;

pe.age = 18; //结构体直接访问

struct people* ppe = &pe;

ppe->age = 18; //指针间接访问 

枚举类型

生活中一些可以一一举例的数据类型可以成为枚举类型

比如性别:男,女;季节:春,夏,秋,冬;

可以定义枚举类型

enum Season // 枚举类型 季节
{
    Spring,
    Summer,
    Autumn,
    Winter    //最后一个没有逗号
};
  
enum Season now = Autumn; //定义枚举变量 now ,初始化为Autumn

可以理解为我们自己定义枚举常量,用这个常量来给我们的枚举变量赋值,类型是相对应的 。

枚举类型中的枚举常量都是有自己的值得,默认从0开始,依次递增,我们也可以给他赋初始值。

enum Season // 枚举类型 季节
{
    Spring = 1,
    Summer = 3,
    Autumn = 4,
    Winter = 5   //最后一个没有逗号
};
  
enum Season now = Autumn; //定义枚举变量 now ,初始化为Autumn, now的值为4

可以用枚举类型替换掉我们平时用的#define,有很多优点,可以一次定义多个常量,不是单纯的替换,可以避免很多问题,便于调试等。

联合体类型

联合体类型是一种特殊的自定义类型,类似于结构体,但是与结构体不同的是,联合体的成员变量共用一块空间,因此联合体也称做共用体

union Un  //联合体的声明
{
   int a;
   char c;
};

union Un x; //联合体的定义

x.a = 5;     //访问联合体成员
x.c = 'p';

C语言数据在内存中的存储

声明和定义的区别

内置类型

告诉编译器我有这个变量,而他的值未知,这是声明。

声明后给变量赋值,系统会为变量开辟空间来存储数据,这是定义。

也就是说,声明和定义的区别就是有没有分配内存。

变量的声明和定义方法如下

int   age;          //  数据类型    变量名称;  这一步是声明

       age = 0;   //分配内存空间,存储数据,这一步是定义

int   cnt = 0;   //声明的时候给他初始化,分配内存空间了,是定义

结构体类型

结构体类型声明和定义在介绍类型的时候已经展示,但也有一些特殊的声明和定义

//匿名结构体:省去struct后面的标签,并且直接定义x
struct
{
    int a;
    int b;
}x;  
//匿名结构体定义时可以定义多个,也可以定义指针
struct
{
    int a;
    int b;
}x1,x2[10],*x; 

*******************************************************************************************
//结构体自引用:在结构体中成员变量可以是自身的指针类型
struct Node
{
    int a;
    struct Node* next; //如果不是指针,就会递归定义,无休无止,所以定义成指针, 
                       //就可以通过自身找到下一个结构体
}

stuct people
{
    char name[10];
    int age;
    float height;
}p1;     // 声明类型的同时定义结构体p1

struct people p2;    // 定义结构体变量p2
struct people p3 = {"张三",21,180};  //定义p3的同时初始化p3

struct Node
{
    int a;
    struct people p;   //结构体嵌套
    struct Node* next; //结构体自引用
}p4 = {1, {"李四", 20, 175 }, &p3};  //结构体嵌套定义初始化

p5 = {2, {"王五", 20, 178 }, &p4};   //结构体嵌套定义初始化

数据存储

 整数类型

在32位机器下,整数会分配4个字节的大小来存放数据,64位机器下是8个字节,每个字节是8个bit位,一个bit就是我们内存的最小单位,只有2种状态,我们可以用它存储2进制代码。

32位机器下,int类型的数据会有4个字节,也就是32个bit位来存放数据。存放时有符号位和数值位两部分。

符号位都是用0表示“正”,用1表示“负”;

原码

直接将整数按照正负数的形式翻译成二进制代码

反码

原码的符号位不变,其他位依次按位取反

补码

反码+1就是补码

正数的原码,补码,反码都是相同的。

在计算机中,整形存储都是存储补码

这样存储补码的原因是:使用补码可以统一处理符号位和数值位。可以统一处理加减法,补码与原码转换,其运算过程是相同的,不需要额外的硬件电路

浮点类型

浮点类型包括float,double,long double类型

存储规则

根据国际标准(IEEE)规定,任意一个二进制浮点数V可以表示成下面形式

其中

  1. 符号位(S):1位,用来表示这个数是正数还是负数。0表示正数,1表示负数。
  2. 指数位(E):8位,用来表示数值的范围。它存在一个偏移值,通常偏移量是127。
  3. 尾数位(M):23位,用来表示数值的精度。

例如,十进制20.0,写成二进制是10100.0 = 1.01 * 2^4.  则S = 0, M = 1.01, E = 4;

 根据IEEE规定,32位浮点数最高位的1位存储符号位S,接着8位是指数E,剩下的23位是有效数字M。

对于64位,最高位为符号位,接着11位是指数E,剩下的52位为有效数字

对于M和E,有特殊规定

M:介于1到2之间,即1.***,默认第一个数总是1,因此可以将1省略,在内存中只存入小数部分,这样做的好处是存储有效数字的位数可以从23变到24

E:E是一个无符号的整数,8个bit位,意味着他的存储范围为0~255,但是科学计数法中E可以为负数,因此我们给E加上127存到内存里,就可以表示-127~128之间的数,对于11位的E,这个数是1023

例如,如果有一个32位的浮点数01000000 00000000 00000000 00000000,那么:

  • 符号位是0,表示这是一个正数。
  • 指数位是10000000,转换为十进制是128,减去偏移量127,得到实际指数是1。
  • 尾数位是00000000 00000000 00000000 00000000,表示小数部分是0。

所以这个数表示的是1 * 2^1 = 2

自定义类型

结构体在内存中存储是,其分配的空间不是各成员分配的空间之和,他还需遵守一个规则,结构体内存对齐

结构体内存对齐

对齐规则:

1.第一个成员在与结构体变量偏移量为0的位置

2.其他成员变量要对齐到某个数字(对齐数)的整数倍地址初,

3.结构体总大小为最大对齐数(每个成员对齐数的最大值)的整数倍。

4.如果有嵌套结构体的情况,成员结构体对齐到自己的最大对齐数整数倍,外结构体对齐到所有对齐数(包括成员结构体)的最大对齐数的整数倍

对齐数的计算

 对齐数 = 编译器默认的对齐数 与 该成员大小的较小值,vs中默认对齐数是8

默认对齐数可以进行修改

#pragma pack(2) // 修改默认对齐数为2

struct Example {
    char a;  // 1 字节
    int b;   // 4 字节
    char c;  // 1 字节
};

#pragma pack( )  // 恢复默认对齐数

举例
struct Example {
    char a;  // 1 字节
    int b;   // 4 字节
    char c;  // 1 字节
};

 如果没有对齐,那他的内存分布是

根据对齐规则后,应该是

a是结构体的第一个成员,在偏移量为0的位置

b是int类型的数据,大小为4个字节,与默认对齐数8相比较小,所以b的对齐数是4,他的位置必须在4的整数倍

c类似,对齐数为1,位置在1的整数倍

整个结构体对齐数位成员对齐数1,4,1 的最大值4,所以他的大小为4的整数倍,所以他的总大小为12个字节

对齐的意义

编译器读取内存可能不是一位一位读取,是同时读取4个字节或者其他整数个字节,以4为例,如果不对齐的话,可能读取一个整数会需要访问两次,因为在他之前可能读过不是4的倍数大小的空间,而对齐后则是可以一次读取,尽管浪费了空间,但是换来了时间

标签:存储,struct,int,数据类型,C语言,pe,类型,对齐,定义
From: https://blog.csdn.net/2301_79969685/article/details/142533953

相关文章

  • 【Leecode 随笔】C语言版看了不后悔系列持续更新中。。。(四)
    文章目录题目一:实现一个函数,计算两个整数的最大公约数(GCD)题目分析:解题思路:示例代码:代码解析:题目二:实现一个函数,判断一个整数是否为素数题目分析:解题思路:示例代码:代码解析:题目三:实现一个函数,对给定的字符串进行排序(按字母顺序)题目分析:解题思路:示例代码:代码解析:......
  • C语言 15 预处理
    C语言学习已经快要接近尾声了,但是有一个东西迟迟还没有介绍,就是一直在写的:#include<stdio.h>这到底是个什么东西,为什么每次都要加上呢?这里将详细讨论它缘由。C语言中带#号的指令并不是C关键字的一部分,不属于C语言。带#号的指令是写给编译器看的,告诉它一些事情,好让......
  • JS数据类型&类型转换
    基本数据类型JS中的数据类型由原始值和对象共同组成,原始值一共有七种原始值:数值(Number)大整数(BigInt)字符串(String)布尔值(Boolean)空值(Null)未定义(Undefined)符号(Symbol)数值和大整数数值(Number):在js中所有的整数和浮点数都是number类型leta=3letb=3.1415926在js......
  • c语言数据类型和变量(下)
    2,变量C语⾔中把经常变化的值称为变量,不变的值称为常量。创建变量的语法形式:data_typename; ||||数据类型变量名变量在创建的时候就给⼀个初始值,就叫初始化。intage=18;charch='w';doubleweight=48.0;unsignedintheight=100;2.2变量的分类•全......
  • c语言数据类型和变量(上)
    C语⾔数据类型和变量数据类型介绍常见来说,使⽤整型类型来描述整数,使⽤字符类型来描述字符,使⽤浮点型类型来描述⼩数。C语言的数据类型分为内置类型和自定义类型,这里主要介绍内置类型。1.1字符型(char)char//character[signed]char//有符号的unsignedchar//⽆符号的1......
  • 实验1 C语言开发环境使用和数据类型、运算符、表达式
    任务1:1#include<stdio.h>23intmain(){4printf("OO\n");5printf("<H><H>\n");6printf("IIII\n");7return0;8} 1#include<stdio.h>23intmain(......
  • PARTIV-Oracle数据库存储结构-内存架构
    14.内存架构14.1.Oracle是数据库内存结构简介当实例启动时,Oracle数据库会分配一个内存区域并启动后台进程。这个内存区域存储以下信息:程序代码每个已连接会话的信息,即使它当前未活跃程序执行期间需要的信息,例如,正在从中提取行的查询的当前状态锁数据等在进程间共享和通信......
  • 实验1 C语言输入输出和简单程序编写
    实验1:源代码1:#include<stdio.h>#include<stdlib.h>intmain(){printf("O\v");printf("<H>\v");printf("II\v");printf("O\v");printf("<H>\v");printf(......
  • 【重生之我】初学C语言之 指针
    指针or地址???指针概念C语言中每个内存单元都有一个编号,有了这个内存单元的编号,CPU就可以快速找到一个内存空间,储存空间中一个字节里面能存放8个比特位。bitBYTEKBMBGBTB比特字节(8bit)1024字节1024KB1024MB1024GB内存单元的编号==地址==指针Cpu从内存单元中拿数据,Cpu算完后数据再储存在......
  • 数据类型
    强类型语言要求变量的使用严格符合规定,所有变量都必须先定义后才能使用基本数据类型整数byte:一个字节(-128~127)short:两个字节int:4个字节long:8个字节long类型后面要加L浮点float:4个字节float类型后面要加Fdouble:8个字节字符类型char:2个字节注意:string不是......