数据类型原创
# 算术型
# 整数型
# int
有符号整型,占
4个字节
内存,取值范围:-~( )-1。 约为21亿。 简写:int i; // 越简单越好,常用
完整写法:signed int i; //不常用
32 位:0000 0000 0000 0000 0000 0000 0000 0000 (最高位为符号位)
从
加到 ,4 个字节,一个字节 8 位二进制。 64 位:0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 (最高位为符号位)
从
加到 。 # short
短整型
2字节
,取值范围:-~( -1),即 -32768~32767
。简写:short i; // 越简单越好,常用
完整写法:signed short int i; //不常用
# long
长整型,
4字节(32位),8字节(64位)
, 取值范围:-~( -1) 或 - ~( -1) 在 32 位系统下,可以使用
long long
定义 8 字节。# unsigned short int
无符号短整型
2字节
,取值范围:0~(-1), 即 65535
。# unsigned int
无符号整型,
4个字节
,取值范围:0~(-1)。 # unsigned long int
无符号长整型,
4 字节(32 位)
,8 字节(64 位)
, 取值范围:0~(-1) 或 0~( -1)。
# 浮点型
浮点数的标准格式(IEEE754 标准):
float(23 位尾数,6~7 位有效数字),1 位数符,8 位阶码,23 位尾数。
double(52 位尾数,16 位有效数字),1 位数符,11 位阶码,52 位尾数。
- long double
# 枚举型 enum
用于数据取值范围有限,且取值全部为整数时。
// 定义枚举变量,并设置参数名字,却没有给出名字对应的值,这是因为枚举值默认从 0 开始,往后逐个加 1(递增);也就是说,week 中的 Mon、Tues ...... Sun 对应的值分别为 0、1 ...... 6。
enum week{ Mon, Tues, Wed, Thurs, Fri, Sat, Sun };
// 定义枚举变量,并给参数赋值
enum week{ Mon = 1, Tues = 2, Wed = 3, Thurs = 4, Fri = 5, Sat = 6, Sun = 7 };
// 更为简单的赋值
enum week{ Mon = 1, Tues, Wed, Thurs, Fri, Sat, Sun };
# 字符型
# char
字符, 1 字节
,取值范围:-128~127。用 ''
包裹。打印时使用 %c
。
# 字符串
用 ""
包裹。打印时使用 %s
。没有支付串数据类型,所有以字符数组形式定义支付串。
点击查看 字符数组
# 字符串操作
以下操作均需要引入头文件 <string.h>
strlen
strlen(xx); //获取字符串或字符数组长度。
strcpy
char *strcpy(char *dest, const char *src)
- dest 指向用于存储复制内容的目标数组。
- src 要复制的字符串。
把
src
所指向的字符串复制到 dest
。缺点:不能复制整型数组以及浮点型数组
#include <stdio.h> #include <string.h> int main () { char src[50], dest[50]; strcpy(src, "This is source");//赋值 strcpy(dest, src); printf("最终的目标字符串: |%s|", dest); return(0); }
memcpy(void *str1, const void *str2, size_t n) 从存储区 str2 复制 n 个字节到存储区 str1
- str1 -- 指向用于存储复制内容的目标数组,类型强制转换为 void* 指针。
- str2 -- 指向要复制的数据源,类型强制转换为 void* 指针。
- n -- 要被复制的字节数。
特点:可以复制整型数组以及浮点型数组
strcat
char *strcat(char *dest, const char *src)
- dest 指向目标数组,该数组包含了一个 C 字符串,
且足够容纳追加后的字符串
。 - src 指向要追加的字符串,该字符串不会覆盖目标字符串。
把 src 所指向的字符串追加到 dest 所指向的字符串的结尾。
- dest 指向目标数组,该数组包含了一个 C 字符串,
strcat(dest, src);
strcmp
nt strcmp(const char *str1, const char *str2)
把 str1 所指向的字符串和 str2 所指向的字符串进行比较。
该函数返回值如下:
- 如果返回值小于 0,则表示 str1 小于 str2。
- 如果返回值大于 0,则表示 str1 大于 str2。
- 如果返回值等于 0,则表示 str1 等于 str2。
s
# 指针
指针本质就是 地址
!主要用于传递与偏移。取地址操作符 &
,也称 引用
。取地址操作符 *
,也成为 解引用
。
提示
指针内存大小与系统有关, 32位系统
指针占 4字节
; 64位系统
指针占 8字节
。
# 指针定义与赋值
// 定义无类型指针
viod *p;
// 定义一个int型指针
int *p;
// 定义一个int型指针w,并将q指针地址赋予w
int q;
int *w=&q; // 实际就是间接访问
直接访问,就是直接对变量地址进行存取:
int i=5;
scanf("%d",&i); // 对变量地址存入数据
printf("%d",i); // 对变量地址读取数据
return 0;
间接访问,即将一个变量地址存放到另一个变量中:
int i=5; // 定义变量并赋值
int *p=&i; // 定义一个 int 指针,并将变量 i 的地址赋值给指针。
printf(“%d”,*p); // 结果为5
# 指针传递
# C指针传递
指针作为形参, 注意此处使用的是 *
解引用。
指针作为实参, 在其他函数中进行使用。 C语言
需要传入指针 &
引用。
#include <stdio.h>
//void change(int **p)子函数修改主函数指针时,二级指针
void change(int *i){ // void 无返回类型函数, C语言无法在形参位置使用 & 引用!
*i = 5; // 解引用
}
int main() {
int i=10;
printf("改变前的值:%d\n",i);
change(&i);// 引用指针 实参
printf("改变后的值:%d\n",i);
return 0;
}
# C++指针传递
指针作为形参, 注意与 C语言
的使用区别, C语言
使用的是 *
解引用,而 C++使
用的是 &
引用。
//void change(int *&p)子函数修改主函数指针时
void change(int &p) // 形参 C++ & 称为引用
{
p++;
}
指针作为实参,在其他函数中进行使用。 C++
直接传入指针名即可。
change(p); // 实参
警告
c++
文件后缀为.cpp
。而c
文后缀为.c
。
# 指针偏移
对指针进行加减偏移,偏移大小与指针类型大小有关。
# C指针偏移
#include <stdio.h>
int main() {
int i[10]={ 1, 2, 4, 5};
int *k;
k = i; // 将 i数组 起始地址传递给 指针K
for (int j = 0; j < 10; ++j) {
printf("int数组第%d个值为:%d\n",j, *(k + j));
}
return 0;
}
指针 自增 自减 偏移的使用:
#include <stdio.h>
int main() {
int i[5]={ 7, 3, 6, 9},j;
int *k;
k = i; // 将 i数组 起始地址传递给 指针K
j = *k++; // 等价于 j=*k; *k++;
// j = (*k)++; // 等价于 j=*k; (*k)++;
printf("j的值为:%d\n",j); // j = 7;
printf("k自增后的值为:%d\n",*k); // 此时 k =3,指针偏移了
(*k)++; // 是 k指针所指空间的值自增,不在是指针偏移!!
printf("(*k)++的值为:%d\n",*k);
return 0;
}
警告
注意 *p++;
与 (*p)++
的区别!!
*p++;
是指针偏移,是按指针基类型大小进行内存空间加减
。(*p)++;
不是指针偏移,是对指针所指向空间的值进行加减
。
# C++指针偏移
#include <stdio.h>
#include <stdlib.h>
// c++ 使用 *& 接受主函数中传递过来的指针,注意符号顺序
void modify_pointer(int *&p){
// malloc 需要引入 stdlib.h 头文件
p = (int*)malloc(20* sizeof(int *));
p[0]=20;
p[1]=15;
}
int main() {
int *p=NULL;// 空指针
modify_pointer(p);// 实参,向子函数传递指针
printf("p[0]=%d\n",p[0]);
printf("p[1]=%d\n",p[1]);
return 0;
}
# 构造类型
# 数组 Array
警告
注意访问越界(即访问超出数组长度)。
数组下标从 0 开始。
数组默认有一个值,该值为 数组起始地址
。数组作为实参传递给子函数时弱化为指针。
#include <stdio.h>
void change(char *c){
// 注意以下操作都是字符操作!!! 使用 ''
*c = 'H'; // 默认指针记为数组第一个值
c[1] = 'E'; // 数组下标,从0开始
*(c + 2) = 'L'; // 指针偏移
}
int main() {
char c[10] = {"welcome!"};
change(c);
printf("改变后的内容:%s\n",c);
puts(c);
return 0;
}
# 一维数组
// 未定义数组长度
int i[]; // 所占内存大小为: 数组长度 * 类型所占内存大小
char c[]; // 虽然 char 只占 1 个字节,但是内存自动对齐(32位4字节),所以内存大小为: 4*数组长度,
// 制定数组长度
int j[10]; // 所占内存大小为: 10*4
long long m[10]; // 32位操作系统,所占内存大小为: 10*8
float j[10]; // 所占内存大小为: 10*4
double k[10]; // 所占内存大小为: 10*8
char d[10]; // 内存自动对齐,所占内存大小为: 10*4
# 多维数组
// 未定义数组长度
int i[][];
char c[][][];
// 制定数组长度
int j[10][];
int k[10][10];
int l[][10];
char e[10][];
char f[10][10];
char g[][10];
# 字符数组
必须要比实际字符串长多多一个字节,因为要多一个
\0
作为字符数组结尾判断。所以:
// 不得操过数组长度
char c[5]="abcd";
printf("%s\n",c);
printf("%d\n",sizeof(c)); // 打出结果为 5
char d[5]="ab";
printf("%s\n",d);
printf("%d\n",sizeof(d)); // 打出结果为 5
// 为定义数组的长度
char e[]="abcdef";
printf("%s\n",e);
printf("%d\n",sizeof(e)); // 打出结果为7 实际字符个数+1
# 结构体 struct
# 结构体定义
//
struct student{
// 结构体内容,包含参数与数据类型
int num;
char name[20];
char gender;
char address[50];
}; // 不能使用别名
使用typedef
起别名!可以缩短结构体的定义。
// 注意typedef 的作用 起别名!!!
//不含有本身指针的时候,struct后可以不用定义名称,直接起别名即可!!!
typedef struct student{
int num;
char name[20];
char gender;
char address[50];
}stu,*pstu;//别名可以有多个! *pstu 等价于 struct student *
// 上述结构体内存大小为整型数组大小加上2个指针大小
// 即:4*10+4+4 = 48 字节
//含有本身指针的时候,struct后必须定义名称
typedef struct LinkNode{ //结构体名称
int data;
struct LinkNode *next;//含有本身指针的时候,struct后必须定义名称
}LinkNode; // 结构体别名,可以与结构体名称一样
// 内存大小为 16??? 为什么
typedef struct LNode{
int data;//定义数据类型
struct LNode *next; //含有本身指针的时候
}LNode,*pLNode; //结构体别名,结构体指针别名
// 如 pLNode P; sizeof(P) 8字节 ; LNode L;sizeof(L); 16字节
警告
typedef
与 define
(宏) 的区别:
typedef
仅限于为类型定义符号名称,define
不仅可以为类型定义别名,也能为数值定义别名,比如您可以定义 1 为 ONE。#define TRUE 1
#define FALSE 0
typedef int INTEGER;typedef
是由编译器执行解释的,define
语句是由预编译器进行处理的。
# 结构体的使用
在函数中使用
- 未使用typedef的结构体
int main() {
struct student s={100,"诚城",'m',"测试地址"};
struct student *p; // 结构体指针
p = &s; // 结构体地址传递给指针
printf("编号:%d;\n姓名:%s;\n性别:%c;\n地址:%s\n",s.num,s.name,s.gender,s.address);
// 指针获取结构体的方式
printf("--------------结构体指针 第一种应用------------------\n");
printf("指针第一种编号:%d;\n姓名:%s;\n性别:%c;\n地址:%s\n",(*p).num,(*p).name,(*p).gender,(*p).address);
printf("--------------结构体指针 第二种应用------------------\n");
printf("指针第二种编号:%d;\n姓名:%s;\n性别:%c;\n地址:%s\n",p->num,p->name,p->gender,p->address);
printf("--------------- 结构体 数组 ---------------------\n");
// 可以存储3个结构体数据的数组
struct student sarr[3]={100,"诚城",'m',"测试地址",101,"诚城1",'m',"测试地址1",120,"诚城2",'m',"测试地址2"}; // 初始化时,内容必须与结构图数据相对应
strcpy(sarr[0].name,"测试");//必须使用 strcpy 对对应的字符型数据内容赋值
sarr[0].num = 88;
sarr[0].gender = 'f';
// sarr[2]={100,"诚城",'m',"测试地址"}; // 无法使用 数组赋值
printf("编号:%d;姓名:%s;性别:%c;地址:%s\n",sarr[0].num,sarr[0].name,sarr[0].gender,sarr[0].address);
printf("------------- 结构体 数组 一 ---------------------\n");
printf("编号:%d;姓名:%s;性别:%c;地址:%s\n",sarr[1].num,sarr[1].name,sarr[1].gender,sarr[1].address);
printf("------------- 结构体 数组 二 ---------------------\n");
printf("编号:%d;姓名:%s;性别:%c;地址:%s\n",sarr[2].num,sarr[2].name,sarr[2].gender,sarr[2].address);
printf("------------- 结构体 指针偏移 --------------------\n");
int n;
// p = &sarr;
p = sarr; // 数组弱化为指针,因此可以不用 & 引用
printf("------------- 结构体 偏移 一 ---------------------\n");
n = p->num++; // 等价于 n= p->num; p->num++; 注意运算的优先级!!
printf("指针偏移一后n的值为:%d, 指针num值为:%d\n",n,p->num);
printf("------------- 结构体 偏移 二 ---------------------\n");
n = p++->num; // 等价于 n= p->num; p++; 注意运算的优先级!!
printf("指针偏移一后n的值为:%d, 指针num值为:%d\n",n,p->num);
return 0;
}
使用
typedef
别名的结构体int main() { // 用结构体别名定义 结构体变量 stu s={100,"诚城",'m',"测试地址"}; // 用结构体指针别名定义 结构体指针变量 pstu p; // 还可以 使用 stu* p; 来定义结构体指针 p = &s; // 结构体地址传递给指针 printf("编号:%d;\n姓名:%s;\n性别:%c;\n地址:%s\n",s.num,s.name,s.gender,s.address); // 指针获取结构体的方式 printf("--------------结构体指针 第一种应用------------------\n"); printf("指针第一种编号:%d;\n姓名:%s;\n性别:%c;\n地址:%s\n",(*p).num,(*p).name,(*p).gender,(*p).address); printf("--------------结构体指针 第二种应用------------------\n"); printf("指针第二种编号:%d;\n姓名:%s;\n性别:%c;\n地址:%s\n",p->num,p->name,p->gender,p->address); return 0; }