四种基本数据类型(四种基本数据类型的存储空间长度排列顺序)

新手小白入门C语言关于数据类型

C 语言包含的数据类型

1、整型

整型分为整形常量和整形变量,常量就是我们平时所看到的准确的数字,例如:1、20、333等等,变量则按我的理解是我像内存去申请一个存储空间,告诉内存空间我申请了这个地方用来存放一个整形的数据,但是什么时候放并没有直接确定。一般占4个字节(32位),最高位代表符号,0表示正数,1表示负数,取值是-2147483648~2147483647,在内存中的存储顺序是低位在前、高位在后,例如0x12345678。

(1)短整型 short(内存中占2个字节)

是short int 的简写。

取值范围:-32768 ~ + 32767 (2 Bytes)

定义常量:short a = 5;

(2)整型int(long int) (4字节)

long是long int 的简写。

取值范围:-2147483648 ~ +2147483647 (4 Bytes)

定义:

int a = 0; //定义最好进行初始化

long a = 0;

//上述两种定义相同。

(3)长整型long long (8字节)

PS:1.C语言标准是这样规定的:int最少16位(2字节),long不能比int短,short不能比int长,具体位长由编译器开发商根据各种情况自己决定。

2.32位平台下long 是4个字节,long long 是8字节;但是64位平台下则全是8字节。因此为了保证平台的通用性,程序中尽量不要使用long数据类型。

2、浮点型

(1)单精度float

系统的基本浮点类型。至少能精确表示小数点后6位有效数字。

一个float类型占用4个字节的存储位。

其中最高位为符号位,紧接着8位为指数位,剩下的23位为尾数位。

格式说明符:%f

(2)双精度double

双精度浮点类型。至少能精确表示小数点后12位有效数字。

一个double类型占用8个字节的存储位。

最高位为符号位,紧接着8位为指数位,剩下的52位为尾数位。

格式说明符:%lf

3、字符型char(1字节)

字符型在其本质上就是整形,我们在C语言中使用char表示一个字符型,他占用一个字符的存储空间,字符型在存储时其内部存储的依旧是二进制数据,当我们读出时将会得到一个整形数据,而我们输出时会得到一个字符是因为我们人为的定义了一个对照表,这个表规定字符a的数值就是97,所以当我们遇到97时我们有两种读出方式,第一种以整数形式读出就是97,另一种就是以字符型读出,使用%c指定读出形。

4、构造类型

4.1 数组

数组是按照顺序存储的一系列类型相同的值,如10个char类型的字符或15个int类型的值。整个数组有一个数组名,通过整数下标访问数组中单独的项或元素。

例如:以下声明:

float debts[20];//声明debts是一个内容20个元素的数组,每个元素都可以存储float类型的值。数组的第一个元素是debts[0],第2个元素是debts[1],以此类推,直到debts[19]。注意,数组元素的编号从0开始,不是从1开始。可以给每个元素赋float类型的值。

例如,可以这样写:debts[5] = 32.54;debts[6] = 1.2e + 21;实际上,使用数组元素和使用同类型的变量一样。

例如,可以这样把值读入指定的元素中:

scanf("%f",&debts[4]);//把一个值读入数组的第5个元素这里要注意一个潜在的陷阱:考虑到影响执行的速度,C编译器不会检查数组的下标是否正确。

下面的代码,其实都不正确:debts[20] = 88.32;//该数组元素不存在!debts[33] = 828.12;//该数组元素不存在!编译器不会查找这样的错误。当运行程序时,这会导致数据被放置在已被其他数据占用的地方,可能会破坏程序的结果甚至导致程序异常中断。

4.2 结构体

结构体是一种自定义的复合数据类型。例如存储学生信息就会用到此种数据类型。

1)定义:

结构体关键字:struct

定义student这种结构体(注意分号不能少),有三个成员变量id,age,name。

struct student{     	long int id;     	int age;     	char name[8]; };

2)声明:

struct student stu1; //定义了一个student类型的变量stu1

3)初始化:

struct student stu1; stu1.id = 12345; //通过成员运算符’.'来访问结构体的成员变量 stu1.age = 20;

strcpy(stu1.age,“Liang”); //因为数组在非初始化时,不能直接通过数组名直接赋值,strcpy函数需要包含头文件string.h 错误的写法:stu1.name = “Liang”;

4)在声明结构体变量时同时初始化,类似于数组初始化。

#include <stdio.h>#include <string.h> struct student {  	long int id;  	int age;  	char name[8]; };   int main(int argc,char* argv[]) {  	struct student stu1 = {12345,22,"Liang"};   	printf("id=%ld age=%d name=%s \n",stu1.id,stu1.age,stu1.name);  	return 0; }

PS:可以使用结构体指针结合"->"来访问成员变量。

例如struct student *sp = &stu1;

sp->id = 12345;

4.3 共用体

关键字:union

共用体也叫联合体,使几个不同类型的变量共占一段内存(相互覆盖),也就是说共用体的成员共用一片内存,后赋值的成员变量的数据才是共用体的生效数据,因为前面的赋值已经被覆盖了。共用体所占内存至少能够容纳最大的成员变量所需的空间,应用场景,比如需要一种既可以存储int型数据也可以存储double型数据的变量。比如识别设备,如果是U盘我要这样读取,如果是手机我又要这样读取……

1)声明共用体变量 、初始化、赋值与结构体类似。(后赋值的成员变量会覆盖前面赋值的成员的数据)

PS:1)同类型的结构体之间可以直接赋值。例如:

C语言的数据类型

C语言的数据类型

2)结构体嵌套

C语言的数据类型

C语言的数据类型

3)匿名结构体 (应用场景:比如限定只有一个超级用户。)

匿名结构体只能在定义结构体的同时声明变量,定义之后无法再声明变量。

C语言的数据类型

4.4 枚举类型

关键字:enum用得很少。

5、指针类型

从根本上看,指针是一个值为内存地址的变量(或数据对象)。正如char类型变量的值是字符,int类型的变量的值是整数,指针变量的值地址。在C语言中,指针有许多用法。

(1)指针的声明

int *p; // 声明一个 int 类型的指针 p

char *p // 声明一个 char 类型的指针 p

int *arr[10] // 声明一个指针数组,该数组有10个元素,其中每个元素都是一个指向 int 类型对象的指针

int (*arr)[10] // 声明一个数组指针,该指针指向一个 int 类型的一维数组

int **p; // 声明一个指针 p ,该指针指向一个 int 类型的指针

PS:所有类型的指针大小都是4个字节(当然这取决与你是多少位的电脑,比如我测试用的是32位,指针理所当然就是4字节)。可以通过下面的代码自行验证:

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>typedef struct book{    char book_name[20];    int book_value;}BOOK;int main(){    BOOK *book_one;    //printf("book_one prt address:%p",book_one);    book_one->book_value = 10;    int *a;    char *b;    short *c;    long *d;    long long *e;    int *arr_save_ten_ptr[10];    int (*ptr_to_arr)[10];    int **p;    //printf("book_one prt address:%p\n",book_one);    printf("size of BOOK struct:%d\n",sizeof(book_one));    printf("size of a:%d\n",sizeof(a));    printf("size of b:%d\n",sizeof(b));    printf("size of c:%d\n",sizeof(c));    printf("size of d:%d\n",sizeof(d));    printf("size of e:%d\n",sizeof(e));    printf("size of arr_save_ten_ptr:%d\n",sizeof(arr_save_ten_ptr));    printf("size of ptr_to_arr:%d\n",sizeof(ptr_to_arr));    printf("size of p:%d\n",sizeof(p));    return 0;}

(2)指针的初始化

/* 方法1:使指针指向现有的内存 */

int x = 1;

int *p = &x; // 指针 p 被初始化,指向变量 x ,其中取地址符 & 用于产生操作数内存地址

/* 方法2:动态分配内存给指针 */

int *p;

p = (int *)malloc(sizeof(int) * 10); // malloc 函数用于动态分配内存,此处分配了40个字节

free§;    // free 函数用于释放一块已经分配的内存,常与 malloc 函数一起使用,要使用这两个函数需要头文件 stdlib.h

(3)未初始化和非法的指针

如果一个指针没有被初始化,那么程序就不知道它指向哪里。它可能指向一个非法地址,这时,程序会报错,在 Linux 上,错误类型是 Segmentation fault(core dumped),提醒我们段违例或内存错误。它也可能指向一个合法地址,实际上,这种情况更严重,你的程序或许能正常运行,但是这个没有被初始化的指针所指向的那个位置的值将会被修改,而你并无意去修改它。

(4)NULL指针

NULL 指针是一个特殊的指针变量,表示不指向任何东西。可以通过给一个指针赋一个零值来生成一个 NULL 指针。

(5)指针的运算

C 指针的算术运算只限于两种形式:

1) 指针 +/- 整数 :

可以对指针变量 p 进行 p++、p–、p + i 等操作,所得结果也是一个指针,只是指针所指向的内存地址相比于 p 所指的内存地址前进或者后退了 i 个操作数。用一张图来说明一下:

C语言的数据类型

在上图中,10000000等是内存地址的十六进制表示(数值是假定的),p 是一个 int 类型的指针,指向内存地址 0x10000008 处。则 p++ 将指向与 p 相邻的下一个内存地址,由于 int 型数据占 4 个字节,因此 p++ 所指的内存地址为 1000000b。其余类推。不过要注意的是,这种运算并不会改变指针变量 p 自身的地址,只是改变了它所指向的地址。举个例子:

2)指针 – 指针

只有当两个指针都指向同一个数组中的元素时,才允许从一个指针减去另一个指针。两个指针相减的结果的类型是 ptrdiff_t,它是一种有符号整数类型。减法运算的值是两个指针在内存中的距离(以数组元素的长度为单位,而不是以字节为单位),因为减法运算的结果将除以数组元素类型的长度。举个例子:

#include “stdio.h”int main(){int a[10] = {1,2,3,4,5,6,7,8,9,0};int sub;int *p1 = &a[2];int *p2 = &a[8];sub = p2-p1;printf("%d\n",sub);    // 输出结果为 6return 0;}

6、空类型 void

常用于没有返回值的空函数。空函数:返回值为void类型的函数,可以用return,也可以不用return。 不用return和在函数结束处有个return是等效的。但要注意return后面除了分号以外什么也没有。

整型分为整形常量和整形变量,常量就是我们平时所看到的准确的数字,例如:1、20、333等等,变量则按我的理解是我像内存去申请一个存储空间,告诉内存空间我申请了这个地方用来存放一个整形的数据,但是什么时候放并没有直接确定。一般占4个字节(32位),最高位代表符号,0表示正数,1表示负数,取值是-2147483648~2147483647,在内存中的存储顺序是低位在前、高位在后,例如0x12345678。

(1)短整型 short(内存中占2个字节)

是short int 的简写。

取值范围:-32768 ~ + 32767 (2 Bytes)

定义常量:short a = 5;

(2)整型int(long int) (4字节)

long是long int 的简写。

取值范围:-2147483648 ~ +2147483647 (4 Bytes)

定义:

int a = 0; //定义最好进行初始化

long a = 0;

//上述两种定义相同。

(3)长整型long long (8字节)

PS:1.C语言标准是这样规定的:int最少16位(2字节),long不能比int短,short不能比int长,具体位长由编译器开发商根据各种情况自己决定。

2.32位平台下long 是4个字节,long long 是8字节;但是64位平台下则全是8字节。因此为了保证平台的通用性,程序中尽量不要使用long数据类型。

2、浮点型

(1)单精度float

系统的基本浮点类型。至少能精确表示小数点后6位有效数字。

一个float类型占用4个字节的存储位。

其中最高位为符号位,紧接着8位为指数位,剩下的23位为尾数位。

格式说明符:%f

(2)双精度double

双精度浮点类型。至少能精确表示小数点后12位有效数字。

一个double类型占用8个字节的存储位。

最高位为符号位,紧接着8位为指数位,剩下的52位为尾数位。

格式说明符:%lf

3、字符型char(1字节)

字符型在其本质上就是整形,我们在C语言中使用char表示一个字符型,他占用一个字符的存储空间,字符型在存储时其内部存储的依旧是二进制数据,当我们读出时将会得到一个整形数据,而我们输出时会得到一个字符是因为我们人为的定义了一个对照表,这个表规定字符a的数值就是97,所以当我们遇到97时我们有两种读出方式,第一种以整数形式读出就是97,另一种就是以字符型读出,使用%c指定读出形式,则对照表则为a。

4、构造类型

4.1 数组

数组是按照顺序存储的一系列类型相同的值,如10个char类型的字符或15个int类型的值。整个数组有一个数组名,通过整数下标访问数组中单独的项或元素。

例如:以下声明:

float debts[20];//声明debts是一个内容20个元素的数组,每个元素都可以存储float类型的值。数组的第一个元素是debts[0],第2个元素是debts[1],以此类推,直到debts[19]。注意,数组元素的编号从0开始,不是从1开始。可以给每个元素赋float类型的值。

例如,可以这样写:debts[5] = 32.54;debts[6] = 1.2e + 21;实际上,使用数组元素和使用同类型的变量一样。

例如,可以这样把值读入指定的元素中:

scanf("%f",&debts[4]);//把一个值读入数组的第5个元素这里要注意一个潜在的陷阱:考虑到影响执行的速度,C编译器不会检查数组的下标是否正确。

下面的代码,其实都不正确:debts[20] = 88.32;//该数组元素不存在!debts[33] = 828.12;//该数组元素不存在!编译器不会查找这样的错误。当运行程序时,这会导致数据被放置在已被其他数据占用的地方,可能会破坏程序的结果甚至导致程序异常中断。

4.2 结构体

结构体是一种自定义的复合数据类型。例如存储学生信息就会用到此种数据类型。

1)定义:

结构体关键字:struct

定义student这种结构体(注意分号不能少),有三个成员变量id,age,name。

struct student{     	long int id;     	int age;     	char name[8]; };

2)声明:

struct student stu1; //定义了一个student类型的变量stu1

3)初始化:

struct student stu1; stu1.id = 12345; //通过成员运算符’.'来访问结构体的成员变量 stu1.age = 20;

strcpy(stu1.age,“Liang”); //因为数组在非初始化时,不能直接通过数组名直接赋值,strcpy函数需要包含头文件string.h 错误的写法:stu1.name = “Liang”;

4)在声明结构体变量时同时初始化,类似于数组初始化。

#include <stdio.h>#include <string.h> struct student {  	long int id;  	int age;  	char name[8]; };   int main(int argc,char* argv[]) {  	struct student stu1 = {12345,22,"Liang"};   	printf("id=%ld age=%d name=%s \n",stu1.id,stu1.age,stu1.name);  	return 0; }

PS:可以使用结构体指针结合"->"来访问成员变量。

例如struct student *sp = &stu1;

sp->id = 12345;

4.3 共用体

关键字:union

共用体也叫联合体,使几个不同类型的变量共占一段内存(相互覆盖),也就是说共用体的成员共用一片内存,后赋值的成员变量的数据才是共用体的生效数据,因为前面的赋值已经被覆盖了。共用体所占内存至少能够容纳最大的成员变量所需的空间,应用场景,比如需要一种既可以存储int型数据也可以存储double型数据的变量。比如识别设备,如果是U盘我要这样读取,如果是手机我又要这样读取……

1)声明共用体变量 、初始化、赋值与结构体类似。(后赋值的成员变量会覆盖前面赋值的成员的数据)

PS:1)同类型的结构体之间可以直接赋值。例如:

C语言的数据类型

2)结构体嵌套

C语言的数据类型

C语言的数据类型

3)匿名结构体 (应用场景:比如限定只有一个超级用户。)

匿名结构体只能在定义结构体的同时声明变量,定义之后无法再声明变量。

C语言的数据类型

4.4 枚举类型

关键字:enum用得很少。

5、指针类型

从根本上看,指针是一个值为内存地址的变量(或数据对象)。正如char类型变量的值是字符,int类型的变量的值是整数,指针变量的值地址。在C语言中,指针有许多用法。

(1)指针的声明

int *p; // 声明一个 int 类型的指针 p

char *p // 声明一个 char 类型的指针 p

int *arr[10] // 声明一个指针数组,该数组有10个元素,其中每个元素都是一个指向 int 类型对象的指针

int (*arr)[10] // 声明一个数组指针,该指针指向一个 int 类型的一维数组

int **p; // 声明一个指针 p ,该指针指向一个 int 类型的指针

PS:所有类型的指针大小都是4个字节(当然这取决与你是多少位的电脑,比如我测试用的是32位,指针理所当然就是4字节)。可以通过下面的代码自行验证:

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>typedef struct book{    char book_name[20];    int book_value;}BOOK;int main(){    BOOK *book_one;    //printf("book_one prt address:%p",book_one);    book_one->book_value = 10;    int *a;    char *b;    short *c;    long *d;    long long *e;    int *arr_save_ten_ptr[10];    int (*ptr_to_arr)[10];    int **p;    //printf("book_one prt address:%p\n",book_one);    printf("size of BOOK struct:%d\n",sizeof(book_one));    printf("size of a:%d\n",sizeof(a));    printf("size of b:%d\n",sizeof(b));    printf("size of c:%d\n",sizeof(c));    printf("size of d:%d\n",sizeof(d));    printf("size of e:%d\n",sizeof(e));    printf("size of arr_save_ten_ptr:%d\n",sizeof(arr_save_ten_ptr));    printf("size of ptr_to_arr:%d\n",sizeof(ptr_to_arr));    printf("size of p:%d\n",sizeof(p));    return 0;}

(2)指针的初始化

/* 方法1:使指针指向现有的内存 */

int x = 1;

int *p = &x; // 指针 p 被初始化,指向变量 x ,其中取地址符 & 用于产生操作数内存地址

/* 方法2:动态分配内存给指针 */

int *p;

p = (int *)malloc(sizeof(int) * 10); // malloc 函数用于动态分配内存,此处分配了40个字节

free§;    // free 函数用于释放一块已经分配的内存,常与 malloc 函数一起使用,要使用这两个函数需要头文件 stdlib.h

(3)未初始化和非法的指针

如果一个指针没有被初始化,那么程序就不知道它指向哪里。它可能指向一个非法地址,这时,程序会报错,在 Linux 上,错误类型是 Segmentation fault(core dumped),提醒我们段违例或内存错误。它也可能指向一个合法地址,实际上,这种情况更严重,你的程序或许能正常运行,但是这个没有被初始化的指针所指向的那个位置的值将会被修改,而你并无意去修改它。

(4)NULL指针

NULL 指针是一个特殊的指针变量,表示不指向任何东西。可以通过给一个指针赋一个零值来生成一个 NULL 指针。

(5)指针的运算

C 指针的算术运算只限于两种形式:

1) 指针 +/- 整数 :

可以对指针变量 p 进行 p++、p–、p + i 等操作,所得结果也是一个指针,只是指针所指向的内存地址相比于 p 所指的内存地址前进或者后退了 i 个操作数。用一张图来说明一下:

C语言的数据类型

在上图中,10000000等是内存地址的十六进制表示(数值是假定的),p 是一个 int 类型的指针,指向内存地址 0x10000008 处。则 p++ 将指向与 p 相邻的下一个内存地址,由于 int 型数据占 4 个字节,因此 p++ 所指的内存地址为 1000000b。其余类推。不过要注意的是,这种运算并不会改变指针变量 p 自身的地址,只是改变了它所指向的地址。举个例子:

2)指针 – 指针

只有当两个指针都指向同一个数组中的元素时,才允许从一个指针减去另一个指针。两个指针相减的结果的类型是 ptrdiff_t,它是一种有符号整数类型。减法运算的值是两个指针在内存中的距离(以数组元素的长度为单位,而不是以字节为单位),因为减法运算的结果将除以数组元素类型的长度。举个例子:

#include “stdio.h”int main(){int a[10] = {1,2,3,4,5,6,7,8,9,0};int sub;int *p1 = &a[2];int *p2 = &a[8];sub = p2-p1;printf("%d\n",sub);    // 输出结果为 6return 0;}

6、空类型 void

常用于没有返回值的空函数。空函数:返回值为void类型的函数,可以用return,也可以不用return。 不用return和在函数结束处有个return是等效的。但要注意return后面除了分号以外什么也没有。

C语言的数据类型

本站部分内容由互联网用户自发贡献,该文观点仅代表作者本人,本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。

如发现本站有涉嫌抄袭侵权/违法违规等内容,请联系我们举报!一经查实,本站将立刻删除。