C语言全面总结-2

C语言基本知识点复习-2

数组

基本的数据类型: char short int float long double
数据类型的作用:告诉编译器要分配多少个内存地址去存放数据。
一个地址,只能存放一个字节的数据。 8 BIT
为什么需要数组???
假设用户需要存放多个相同的数据类型的数据,那么我们就需要开辟一片很大的内存空间。
如果使用之前的,int a1,int a2,int a3 …这种方式来定义这些数据的话,就会很麻烦。
所以我们就引入数组的技术去解决这些问题!!!!
数组:开辟一块连续的空间地址,来存放相同的数据类型。
数组的定义
语法:
基本的数据类型 数组名[数组的大小];
例子:
int a[100]; //定义一个大小为 100 的int 型数组
char a[4]; //在内存中画出该数组的分配图
数组引用:

  1. 数组都是从0下标开始引用的
    例如:
    int a[4];
    可用下标:
    a[0],a[1],a[2],a[3];
  2. 数组名表示的是地址
    例如:
    int a[4];
    a -> 表示地址
    a[0] -> 表示的是变量
    &a[0] -> 代表的是地址
    对比:
    int a;
    a -> 表示的是变量
    &a -> 表示的是地址
  3. 对数组的元素进行赋值
    1.在定义数组的时候对元素进行整体赋值
    int a[10]={1,2,3,4,5,6,7}; //对前7个元素进行赋值,后面没有赋值的都为0
    2.在定义数组后对单个元素进行赋值 //不是的,有时候会是其他值,但一般为0
    int a[10];
    a[0] = 1;
    a[1] = 2;
    a[2] = 3;
    3.在定义数组后把清空
    int a[10]={0};
    4.错误赋值方式
    int a[10];
    a={1,2,3,4,5,6,7,8}; //错误的!!!!a 是一个地址,是一个常量,常量不能赋值。
    特别的数组:
    int a[]={1,2,3,4,5,6,7}; //缺省数据,在定义的时候系统会自动根据数组赋值的元素个数去确定数组的大小
    //错误的!!!!缺省数组只能在定义的时候赋值
    int a[];
    a[0]= 1;
    a[1]= 2;

变长数组:
int a=10;
int arry[a]; ->一个变长数组,根据a的值去确定数组的长度
注意:变长数组不能赋初值。 例如:int arry[a]={1,2,3,4,5}; //错误的!!!
通过引用符号操作数组:
*-> 可以作为引用符号
[ ] -> 也是一次解引用的过程
注意:只有地址才有解引用!!!!!!!! 只有地址才可以 * 或者是 []
*(a+n)等价于a[n]
字符串数组的操作:
定义一个字符串数组:
char a[100];
对字符串数组进行赋值:

  1. 对字符串数组进行整体赋值 (不够的都补0)
    char a[100]={“abcdefg”};
    char a[100]=“abcdefg”;
    char a[100]={‘a’,‘b’,‘c’,‘d’,‘e’,‘f’};
    注意:如下的错误写法
    char a[100];
    a=“abcdefg”; // 错误的!!!!! a 是一个数组名,就是数组的首地址,所以常量不能赋值。
    char a[4]={“abcd”}; //空间不够,abcd占用4个字节,但是还有一个 ‘\0’ 需要存放。
  2. 对字符串数组中的某个元素进行赋值
    char a[100];
    a[0] = ‘a’;
    *(a+1) = ‘b’; 等价于 a[1]
    a[2] = ‘c’;
  3. 利用函数对数组名进行整体赋值
    #include <string.h>
    char *strcpy(char *dest, const char *src);//作用把src 里面的字符串赋值给 dest 数组 (只能用于字符串数组)
    例子:
    char a[100]={0};
    strcpy(a,“abcdefg”); //对数组名进行整体赋值

传递数组给函数和函数返回数组
传递数组给函数:可以通过不带索引的函数名传递一个指向数组的指针
函数返回数组:声明一个返回指针的函数,另外,C 不支持在函数外返回局部变量的地址,除非定义局部变量为 static 变量。


指针

指针是什么: 指针是一个变量,储存了另一个变量的地址.
指针声明的一般形式:

type *pointerName

其中type必须是有效的C 数据类型, *代表这个变量是一个指针 ,pointerName是指针的名字
所有指针的数据类型都是一样的 都是一个指向地址的十六进制数 不同的只是指针所指向的变量或常量数据类型不同
指针的使用:
定义时 int p 这里的代表数据类型是指针
&为取址符,例如 p=&a 表示取变量a的地址(引用地址)
在使用指针访问值的时候,例如printf(“value of a is %d”,*p) 这里的 * 表示取p地址指向变量的值(解引用)
空指针
指向NULL的指针为空指针 一般定义指针时没有确切的地址时可以赋值为NULL,表示该指针不指向任何地址
指针的运算:
比如ptr表示一个指针,该指针指向一个32bit的地址 ,如果ptr=1000,那ptr+1=1004


字符串

例如:char s[ ] = “hello world”
字符串都以 \0 结尾
一些常用的函数
strcpy (s1,s2) :将 s2 copy到 s1 中
strcat (s1,s2) :将 s2 连接到 s1 的末尾
strlen (s1) : 求 s1 的实际长度 (不包括结尾的 \0)
strcmp (s1.s2) : 比较 s1 和 s2 如果相同返回 0 ;如果 s1< s2返回 小于0 ;如果 s1 > s2 返回大于 0
strchr (s1,ch1) : 返回一个指针,指向字符串 s1 中字符 ch 的第一次出现的位置。
strstr(s1, s2) :返回一个指针,指向字符串 s1 中字符串 s2 的第一次出现的位置
一些注意的地方

  1. 因为结尾有 \0 的存在 所以在 char s[ ] = “hello world” 时 sizeof(s)其实等于12 但是strlen(s)只等于11
  2. 可以使用 \0 来判断一个字符串的长度 (比如用一个循环while(s[i]!=’\n’)就可以从头遍历到最后一个有效字符)

结构体

结构体定义:
结构体是一种可以储存不同类型数据类型的一种数据类型

struct  structName{   						//struct关键字   结构体名称
	structMemberType   structMemberName;	//结构体成员类型(只能是基本类型例如int char)   结构体成员名
	structMemberType   structMemberName;
	.......
};											//结尾记得加 ;

结构体也是一种数据类型 用法与变量、指针一样
例子:定义一个学生出来 ,学号,姓名,班级。

struct student
{
	int  id;     //学号
	char name[1024]; //姓名
    char class[1024];//班级 
};

struct student (变量类型)就是一种新的数据类型
使用struct student 模板定义两个结构体变量 :

struct student jerry,cherry;  //这里的jerry和cherry就是两个数据类型为struct student的两个结构体

通过结构体定义结构体内变量

	jerry.id=18888strcpy(jerry.name,"jerry");
	strcpy(jerry.class,"一班");

通过结构体指针定义结构体内变量

	struct student *ptr;
	ptr=&jerry
	ptr->id=18888;
	strcpy(jerry->name,"jerry");
	strcpy(jerry->class,"一班");

综上所述 结构体用" . " 结构体指针用 "-> "
注意 !!! 对于name和class用strcpy是因为 name和class只是数组名 AKA 是数组的首地址
变量地址对齐原则
结构体的空间分配是按照字节对齐的方式去分配的:1字节对齐,2字节对齐,4字节对齐。
按照最大的数据类型的字节数去对齐。 (字节对齐,就是每次分配空间的时候会分配多少个空间)
分配空间后会使用一部分,然后留下另有部分给下一个数据去使用,假设不够,则重新分配,够的话就直接使用。
所以在定义结构体时,尽量把相同的数据类型放到一起!!

struct  test
{
	int a;   //4 
	char b;  //4
	int c;   //4
	short d; //4  

};   //分配的内存空间  16 
struct  test
{
	int a;   //4 
	int c;   //4
	short d; //4  
	char b;  
};   //分配的内存空间  12 

以上的代码第一个用sizeof求到的空间大小的16 第二个为12
一点引申~为什么要有地址对齐?
这是因为处理器的处理策略不同 如32位处理器一次会取4位数据 若像下图一样 在没有地址对齐的要求下 读取一个double 数据需要cpu去读取三次
地址未对齐
但是地址对齐的情况下只需要读取两次 如下图
在这里插入图片描述


共用体

共用体也称为联合体 和结构体类似 不同在于结构体的各个成员储存空间相互独立 而共用体中的成员之间公用储存空间
比如:

union  example{
int a;
double b;
char c;
}

其中共用体的大小等于成员中数据类型最大的数据的大小 所以为8
由于公用内存 所以这些成员之间是相互覆盖的 也就是说 同一时间只有一个数据是有效的 所以共同体比较适合互斥的数据类型 比如说一个红绿灯要不就是红灯 要不就是绿灯 要不就闪黄灯 不可能同时亮两种颜色


枚举

比较鸡肋的一种数据类型 有时间再回来写写吧

TO BE CONTINUE…

  • 4
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值