C语言数据结构相关基础

数据类型、运算符和表达式

数据类型

在C语言中,数据类型可分为基本数据类型、构造数据类型、指针数据类型等。基本数据类型的最主要特点为:其值不可再分解为其他类型,即基本数据类型是自我说明的。

数据类型分类

常量

  • 整型常量
  1. 十进制:无前缀/后缀,且首字母不为0
  2. 八进制:以0为前缀,如017表示15
  3. 十六进制:以0x/0X为前缀,如0xA0表示十进制160
  4. 整型常量的后缀(后缀加l/L表示长整型,加u/U表示无符号整型常量,同时加必须保证大小写相等)。
  • 浮点型常量
  1. 十进制小数形式:由数字和小数点组成,必须有小数点。例:0.0、100. 、-3.14
  2. 指数形式(一个浮点数可以无整数部分或小数部分,但是不能二者全无。一个浮点数可以无指数或小数,但是不能二者全无 [±][整数部分][.][小数部分][(e,E)±n][后缀]
    如:.23e+12 、1. 、25E5 、+1.23e-4f
  • 字符型常量:字符型常量是用单引号括起来的一个字符。占一个字节,其值就是该字符的ASCII码值。\表示转移
  • 字符串常量:字符串常量是用双引号括起来的。字符串的最后自动加字符’\0’,表示字符串结束。
  • 符号常量:如# define 标识符 常量 例:# define PI 3.1415926

变量

在程序执行过程中,值可以改变的量称为变量。一个变量应该有一个名字,同时在内存中占据着一定的存储单元。命名规则为:

  • 必须以英文字母或者下划线开头,由字母、数字和下划线组成。
  • 不能与关键字重名,长度受限制,对大小写敏感。
    数值类型的长度和值域

运算符

C中运算符的优先级

  • 算术运算时的自动类型转换
  1. short,char -> int
  2. int -> unsigned -> long -> unsigned long -> double
  3. folat -> double -> long double
  • 强制类型转换:(类型名)表达式,例如(int)m
  • 常见问题:数据溢出,浮点变量的舍入误差,忽略变量类型进行不合法的运行等。

表达式

  1. 基本赋值表达式:左值表达式=右值表达式
  2. 复合赋值表达式: += -= *= /= %= &= |= ^= <<= >>= 左op=右 等价于 左=左op右
  3. 条件运算表达式:表达式1? 表达式2:表达式3 表达式1成立则运行表达式2,否则执行表达式3。
  4. 逗号表达式:表达式1,表达式2,……表达式n。先求表达式1的值,再求2,依次计算到n,则表达式n的值就是逗号表达式的值。

变量的存储类型

变量的数据类型决定了该变量所占内存单元的大小及形式,变量的存储类型决定了变量的存储区域,因而规定了其作用域、生存期及可见性。
对于一个正在运行的程序,其内存分为三个区域:程序代码区(程序的指令代码),静态存储区(静态存储变量存放区,包括全局变量),动态存储区(存放局部自动变量、函数的形参以及杉树调用时的小车包含和返回地址)。动态存储区包含数据区和堆栈区。
变量定义的一般形式:<存储类型> <数据类型> 变量名表

  • 自动型变量auto:在函数内或复合语句中可缺省;只能做内部变量,只在定义它的函数或符合语句中有效,}后即释放。
  • 寄存器型变量register:数据在寄存器中操作比在内存中快得多,把使用率高的少数几个变量定义为register,可以大大加快程序的运行速度。作用域和寿命同auto型。
  • 外部参照型变量extern:一般用于程序的多个编译单位之间传送数据。
  • 静态型变量static:static变量是全局寿命。全局static变量全局可见,局部static变量局部可见。
  • auto型和register型变量的内存是动态分配的,初始值是不定的,每次都要重新初始化,不一定为0。
  • static型和外部参数型变量的内存是全局存在的,分配内存后在整个程序运行完毕后才释放,其初始值为0。

数组

数组的定义及初始化

数组的定义:<存储类型> <数据类型> 数组名

  • 数组下标不允许包含变量
  • 数组名表示数据存储区域的首地址。data和&data[0]表示首地址
  • 数组作为一个整体不能参加各种运算,只有数组的元素变量可以进行数据处理
  • 数组可以进行初始化。数组最好进行初始化操作,如下:int a[3][2] = {1,2,3,4,5,6}; 或者 int a[3][2] = { {1,2,3},{4,5,6} };

数组排序

  • 选择排序法:先找出全部的最小数,再找出除了最小数之前的最小数,最后得到从小到大排序数组。
  • 冒泡排序法:比较相邻两个数据,冒泡排序,最后可得到最大的数字,最终得到从小到大排序数组。

字符数组

  • 一维字符数组:char string[20]={‘s’,’t’,’r’,’i’,’n’,’g’,’\0’};(‘\0’表示结束),string则表示”string”
  • 二维字符数组:char string[3][10]={"how","are","you?"}; string[0]表示”how”……
  • 字符串处理函数
  1. gets(字符数组) 该函数的功能是从键盘输入一个字符串到字符数组中
  2. puts(字符数组) 该函数的功能是将一个字符串输出到终端
  3. strcpy(字符数组1,字符数组2) 将字符数组2中的字符串复制到字符数组1中
  4. strcat(字符数组1,字符数组2) 把字符串2中的字符串连接到字符数组1的后面,结果放在字符数组1中
  5. strcmp(字符串1,字符串2) 把字符串1和2逐个字符进行比较(ASCII),知道出现不同的字符或遇到’\0’。相等返回0;1大于2,返回正整数;1小于2,返回负整数
  6. strlen(字符数组) 测试字符串的长度,并返回。不包含’\0’

指针

指针是C语言的一大特征。利用指针可以直接对内存中各种不同数据结构的数据进行快速处理,并且指针为函数间各类数据的传递提供了简捷便利的方法。

指针的概念

  • 计算机的内存是以字节为单位的一片连续的存储空间,每个字节都有一个编号——内存的地址。内存为地址和存放的内容。
  • 高级语言提供了通过各种名字而不是地址的方式来访问内存的方法,即系统给变量名和变量地址间建立了关系表。
  • C语言中有一种特殊性质的指针变量,其为存放地址的变量。即指针变量指向了一个地址的内存区域。
  • 在程序中,参加数据处理的量不是指针本身的量,因为指针本身是个地址量。指针的目标才是要处理的数据。

指针变量的定义和使用

  • 指针变量的定义:<存储类型> <数据类型> *指针名 (存储类型指指针的类型,数据类型指指针内容的类型)
  • 指针变量的初始化:<存储类型> <数据类型> 指针名[=初始地址值] (它不是一个运算表达式,地址值是赋给指针的)
    例:int
    pa=&a;等同于 int *pa;pa=&a;
  • void指针:定义一个指针变量,不定义指向哪种具体的数据类型,称为“无类型指针”。
  • &为取地址运算符,*为取内容运算符。
  • 使用指针的目的是用指针引用变量,所以必须使指针指向确定的目标对象。
    以下为错误:int p; p=5; 要把p指向变量等对象。

指针运算

  • 对于不同数据类型的指针p,p+n表示p+n*sizeof(p)(字节)
  • 指针p1和p2之间的数据个数:指针p1-p2 表示 (p1-p2)/sizeof(p)
  • malloc函数获取内存空间,free释放malloc函数获取的空间,成对出现。

结构和联合

结构的作用是将不同数据类型的数据组合成一个有机的整体,不仅为处理复杂的数据结构提供了手段,而且为函数间传递不同类型的数据提供了便利。

结构的定义以及结构变量的定义和使用

  • 结构的定义:struct 结构名{ 数据类型 成员名1;数据类型 成员名2;……数据类型成员名n};
  • 结构变量的定义:<存储类型> struct 结构名 结构变量名 ={初始数据};
  • 结构的使用形式:结构变量名.成员名

联合

  • 联合体在定义、说明和使用形式上与结构相似,二者本质上的不同仅在于使用内存的方式上。

    类型定义语句和枚举类型

  • C语言为编程者提供了一种新的类型名来代替已有的基本数据类型名和已经定义的类型的功能。例: typeof unsigned char BYTE;
  • C语言把一组整型符号常量按顺序集合成一种数据类型,称为枚举类型。如:enum WEEKDAY{sun,mon,tue,wedthu,fri,sat}

各种类型的数值占的内存

8bit为一个字节,32位一个字长为4字节,64位一个字长为8字节

类型 C语言 C++
bool 1
char 1 1
wchar_t 2
short 2 2/4(34/64bits)
int 2/4/4(16/32/64bits) 4
long 4/4/8(16/32/64bits) 4/8
float 4 4
double 8 8
long double 12/16(32/64bits) 16
point * 4/8(32/64bits) 4/8
{} 1 1

一般,short为半个机器厂,int为一个机器长(64位,4个字节长),long为一个或两个机器厂。