C语言规定,在程序中使用的每一个数据都必须指定其数据类型。声明变量的时候需要指明数据类型,声明函数的时候也需要指明函数的返回值数据类型。
C语言的数据类型分为:基本类型、构造类型,指针类型,空类型。
基本类型又分为:字符类型(char),整型(int、short、long),实型(float、double),枚举类型(enum)
构造类型又为分:数组,结构体(struct),共用体(union)
不同的数据类型点用的内存空间是不同的,可以用sizeof运算符来计算出各种数据类型占内存的大小,单位是字节
一、基本类型
基本类型分为:字符类型(char),整型(short,int,long),实型(float,double),枚举类型(enum)
字符、整型又分为有符号和无符号,无符号要用关键字unsigned标识,它们的取值是有大小限制的
'a','1','(等这些都属于字符类型,这些字符是以对应ASCII码的值存在内存中的,本质上字符类型就是一个1个字节大小的整型。char取值范围:-128到127(-2^7~2^7-1)
short取值范围:-32768到32767(-2^15~2^15-1)
int取值范围:-2147483648到2147483647(-2^31~2^31-1)
long取值范围:-2147483648到2147483647(-2^31~2^31-1)
unsigned char取值范围:0到255(0~2^8-1)
unsigned short取值范围:0到65535(0~2^16-1)
unsigned int取值范围:0到4294967295(0~2^32-1)
unsigned long取值范围:0到4294967295(0~2^32-1)
注意C语言是没有字符串类型的,在C语言中是用字符数组来表示字符串的,比如:char a[]="hello world"或char a[20]="hello world",但不能char a[20];a="hello world"
枚举类型基本格式为:
enum 枚举类型名 { 枚举常量1[=整型常数],枚举常量2[=整型常数],.....};
"[=整型常数]"是给枚举常量赋值的,是可以省略的。如果不赋初值,编译器会为每一个枚举常量赋一个不同的整型值,从第一个0,第二个1等,依次加1给每一个成员。
比如:enum Week { 星期一, 星期二, 星期三, 星期四, 星期五, 星期六, 星期日 };
#include <stdio.h>
enum Week { 星期一, 星期二, 星期三, 星期四, 星期五, 星期六, 星期日 };//枚举类型的定义
enum color {Black,White,Red,Blue,Green,Brown};
void main()
{
printf("%d\n", sizeof(char));//char占1个字节,a,b,c
printf("%d\n", sizeof(short));//short占2个字节
printf("%d\n", sizeof(unsigned short));//无符号short占2个字节
printf("%d\n", sizeof(int));//int占4个字节
printf("%d\n", sizeof(long));//long占4个字节
printf("%d\n", sizeof(float));//float占4个字节
printf("%d\n", sizeof(double));//double占8个字节
enum color c1 = Green;
printf("Green is %d\n", c1);//输出Green is 4,
char a = '(';//字符
//整型
int b = 10;
short c = -1;
long d = 12345;
unsigned int e= 123;
//浮点型
float fb = 3.14f;//f可有可无
double g = 3.14;
printf("%f\n", fb);
printf("%lf\n", g);
getchar();
}
二、构造类型
1.数组
数组是具有相同类型的一组有序数据的集合,数组在内存中占用一段连续的存储空间
#include <stdio.h>
#define N 5
void main()
{
//数组的定义,数组在内存是连续排列的,[]里的数字表示元素的个数,[]有多少个就表示多少维数组
//一维数组
int a[5] = {1,2,3,4,5};
int c[] = { 1,2,3,4,5 };
int b[5];
b[0] = 0;//初始化,数组的下标是从0开始的
b[1] = 1;
b[2] = 2;
b[3] = 4;
b[4] = 6;
/*可以用for循环语句来初始化数组
for (int i = 0;i < 5;i++)
{
b[i] = i;
}
*/
/*
int n = 5;
int d[n];
定义数组时的[]里的元素个数不能用变量,只能用常量
*/
int d[N];//N是一个常量,所以是可以的
int e[5] = { 0 };//数组全部元素初始化为0
int f[5] = {1,2,3};//只是前3个元素初始化,后面的元素自动初始化为0
printf("%d\n", sizeof(a));//求内存占多少,输出20,元素的个数*数据类型占内存的大小
printf("%d\n", sizeof(a) / sizeof(int));//求数组多少个元素,输出5
//输出数组元素,数组的下标是从0开始的,下标可以用常量,也可以用变量,也可以用表达式
for (int i = 0;i < 5;i++)
{
printf("%d\n", a[i]);
}
for (int i = 0;i < 5;i++)
{
printf("%d\n", b[i]);
}
//二维数组,二维数组可以当作一个一维数组,每一个元素又是一个一维数组,可以把它看作m行n列。二维数组和多维数组其实就是一个特殊的一维数组
int a1[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};//也可以int a1[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}}
for (int i = 0;i < 3;i++)//显示二维数级组
{
for (int j = 0;j < 4;j++)
{
printf("%-6d", a1[i][j]);
}
printf("\n");
}
for (int i = 0;i < 12;i++)
{
printf("%-6d", a1[i / 4][i % 4]);//可以用a1[i / 4][i % 4]读出二维数组的全部元素
}
printf("\n");
//二维数组前面一个[]里的数字在初始化时是可以省略的。多维数组初始化时只有第一个[]里的数字能省略
int a2[][4] = { {1,2,3,4} };//这样也是可以的
/*
int a3[3][] = { {0},{0},{0} }这样是不可以的
int a4[][4];只是声明是不可以省略第一个[]里的数字
int a5[3][4]={{1},{2},{3}}和int a5[3][4]={{1,0,0,0},{2,0,0,0},{3,0,0,0}}是一样的
全部初始化为0与一维数组是一样的
int a6[3][4]={0};
*/
/*
二维数组地址的引用
元素a[i][j]的地址是&a[i][j],也是a[i]+j,&a[i][j]等价于a[i]+j。二维数组的数组名代表该数组的首地址,比如a代表&a[0][0]
二维数组每一行的首地址为a[0],每二行的首地址为a[1],......,第n行的首地址为a[n-1]
二维数组元素的引用
数组名[行下标表达式][列下标表达式],如a[0][0]、a[i][j],a[i][j]与*(&a[i][j])与*(a[i]+j)等价
*/
getchar();
}
2.结构体
结构体是一种构造数据类型,用来把不同类型的数据组合成一个整体。
结构体类型定义:
struct [结构体名]
{
类型标识符 成员名;
类型标识符 成员名;
类型标识符 成员名;
......
};
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
//结构体定义第一钟形式
#define Info1 struct info1//用Info1代替struct info1定义结构体
Info1//结构体定义,定义结构体类型。这里没有分配内存
{
char phone[20];//字符串,其实就是一个数组
char name[10];
char sex[3];//字符
int age;//整型
float score;//浮点型
};
Info1 myinfo4, myinfo5;//结构体变量
//结构体定义第二钟形式
struct info//结构体定义,定义结构体类型。这里没有分配内存
{
char phone[20];//字符串,其实就是一个数组
char name[10];
char sex[3];//字符
int age;//整型
//int age=2;//不能直接赋值
float score;//浮点型
};
struct info myinfo1, myinfo2, myinfo3;//创建三个结构体变量
//结构体定义第三钟形式
struct info2//结构体定义,定义结构体类型。这里没有分配内存
{
char phone[20];//字符串,其实就是一个数组
char name[10];
char sex[3];//字符
int age;//整型
float score;//浮点型
int info2;//成员名可以和类型名相同
} myinfo6={"13525483578", "小强", "男", 18, 80,2 },myinfo7,myinfo8;//myinfo6,myinfo7,myinfo8结构体变量,可以直接在这里初始化,也可以不初始化
struct//无名结构体
{
char phone[20];//字符串,其实就是一个数组
char name[10];
char sex[3];//字符
int age;//整型
float score;//浮点型
} myinfo9 = { "13525483578", "小红", "女", 18, 80 }, myinfo10, myinfo11;//无名结构体变量是有限的,只能在这里声明定义变量
//结构体嵌套
struct MyAllInfo
{
int data;
char remark[200];
struct info info1;
};
/*
struct是关键字,不可以省略。info是结构体名,是可以省略的,省略后叫做无名结构体
struct info是结构体类型,不分配内存,不能赋值、存取、运算。
结构体是可以嵌套定义
定义结构体时计算机还没有为它分配内存,只有在创建一个结构变量后才会分配内存的,分配的长度大于等于所有成员变量所占字节数之和。
不能直接在定义结构体时给里面的成员变量赋值
无名结构体也叫匿名结构体,就是不指定结构体的名称,但一定要在结构体定义的同时声明至少一个结构体变量,否则是没有意义的,是不能在以后程序中声明这钟类型的变量
*/
void main()
{
//结构体初始化第一种形式,就是一个个成员赋值
struct info myinfo;//创建一个变量,struct info是一个整体,不可省略struct
myinfo.age = 20;//myinfo.age这样来访问内部成员
myinfo6.age = 18;
int age = 19;//结构体成员名和程序中的变量名是可以相同的
//myinfo.name = "name";//字符串是不能这样直接赋值的。
//初始化字符串要用sprintf或strcpy,要使用这两个函数要关闭安全检查#define _CRT_SECURE_NO_WARNINGS,strcpy要把string.h包含进来才能用
sprintf(myinfo.name, "小明");
printf("姓名:%s\n", myinfo.name);
strcpy(myinfo.phone, "13525483578");
printf("电话:%s\n", myinfo.phone);
myinfo7 = myinfo6;//结构体变量可以直接赋值结另外一个结构体变量,不过要相同类型才行,整体赋值时里面的字符串也能直接赋值
printf("姓名:%s\n", myinfo7.name);
/*
myinfo = { "13525483578","小明" ,"男",18,80 }
这样是不行的,结构体变量用大括号赋值,只能在创建并初始化才可以
*/
//结构体初始化第二种形式
struct info myinfomation = {"13525483578","小明" ,"男",18,80};
printf("我的姓名是%s\n", myinfomation.name);
//结构体初始化第三种形式,像上面结构体定义第三钟形式里的那样,直接初始化
printf("我的姓名是%s\n", myinfo6.name);
//无名结构体
printf("我的姓名是%s\n", myinfo9.name);
//嵌套
struct MyAllInfo allinfo;
allinfo.data = 100;
sprintf(allinfo.remark, "I am a student");
allinfo.info1.age = 22;//给嵌套的结构体变量的成员赋值
printf("%d,%d\n", allinfo.data, allinfo.info1.age);
//结构体数组,结构体数组的定义跟结构体的定义是一样的,只不过声明变量时是用数组而已。初始化跟数组一样
struct info arrinfo[3] = { {"13525483578","小明" ,"男",18,80},{ "13525483575", "小强", "男", 20, 80 },{ "13625483578", "小红", "女", 18, 90 } };
for (int i = 0;i < 3;i++)
{
printf("姓名:%s,性别:%s,年龄:%d,电话:%s,分数:%.1f\n", arrinfo[i].name, arrinfo[i].sex, arrinfo[i].age, arrinfo[i].phone, arrinfo[i].score);
}
getchar();
}
3.共用体
共用体的用途:使几个不同类型的变量共占一段内存(相互覆盖)
共用体的定义、初始化和引用都和结构体类似,只不过关键把struck换成union,也不能在定义共用体变量时初始化。
用大括号初始化时,只能初始化第一个。
共用体变量任何时刻只有一个最后成员存在,它分配内存长度>=最长成员所占字节数,它分配内存长度要能整除最小成员的字节数。
比如:最大成员所占字节数是9,最小成员所占字节数是2,那么这个共用体所占内存长度不是9,而是10,因为还要被2整除。
共用体变量可以直接赋值给另外一个共用体变量。
共用体定义:
union [共用体名]
{
类型标识符 成员名;
类型标识符 成员名;
类型标识符 成员名;
......
};
union[共用体名] a, b;
union [共用体名]
{
类型标识符 成员名;
类型标识符 成员名;
类型标识符 成员名;
......
}a,b;不能在这里对变量初始化,这个跟结构体不同
union
{
类型标识符 成员名;
类型标识符 成员名;
类型标识符 成员名;
......
}a, b;
三、指针类型(在后面单独学习)
四、空类型(void)
void类型表示为空类型,不是空的意思,而是代表任意类型。
一般用在指针和函数里,用在指针里叫空指针,又叫万能指针,就是未知类型的指针。
用在函数前面时表示无返回值,作为参数时表示无参数。