C语言笔记(六):数组、指针、枚举

数组

在c里面。没有字符串。字符串也就把char的数组拼接在一起的。通过看jdk源码。当然java里的String也是这样的。也就是说,数组是用来存储数据的一种数据结构,也是键值对的存储类型。通过数组下标(指针地址)来获取对应的数据,就像超市的储物柜一样。对应的号码放对应的东西。

数组名是数组第一个元素的地址

声明数组

也就是创建数组。只不过是空数组,里面没有放东西。这也算是一种定义空数组的写法。看代码

int box[10];

首先声明,这个数组是int类型的,也就是说,这个叫做box的数组只能存放int类型的数据。而这个【】里的10,表示能存放10个数据,当然,在计算机里,都是以0开始计数的。所以这里的索引也就是对应存物柜的号码就0~~9;这样就声明好了一个数组,也就是创建了一个空数组。

这个【】的位置是可以放在数组名后面的。

这个【】的位置是可以放在数组名后面的。

这个【】的位置是可以放在数组名后面的。

这里提示一下初始值吧。如果是作为局部的数组,也就是在函数体内。那么初始值还是乱码。除非你给他赋值一个相应类型的值,然后其他九个就是相应类型的初始值了。这里的 int 的初始值也就是0;

初始化数组

初始化有很多种写法。也就是给创建的空数组赋予一个初始值。

在初始化数组的时候,多个数据用逗号分隔

首先看写法一:

int box [10]={1,2,1,2,1,3};

这里就给了这个box数组6个元素。本来是可以放10个的,那么后面的4个就是数组类型int的初始值0;则其实是1、2、1、2、1、3、0、0、0、0,但是一般既然没有给后面的赋值,说明没有用到后面的,也就说,要知道后面是用0来填充的

这里注意,赋值的时候不能超过方括号里定义的值,也就说本来你规定了只能放10数据,你如果多放了,比如放了11个数据,那么就会出现数组越界的报错。就像杯子装满了,溢出来了一样。

写法二:
如果是直接给你要定义的数组赋值,那么c为了不浪费空间,因为可能是你用不了怎么多嘛,就像写法一,你定义了10个位置,实际上只用了6个,就浪费了4个位置。当然不是说这样浪费不行,为了让读取效率高一些,就能用这种写法:

int box2 []={1,2,1,2,1,3};

这里还是定义了一个数组,叫做box2,当然这里的【】里就没有东西了,但是不代表【】能省略,【】是数组的一个代表。这里知道你存放了6个数据,其实c编译器识别到了,会自动在【】里写上6的;

主要的初始化就是楼上两种。但是一定要注意。一个【】叫做一维数组,几个【】就叫几维数组。,所以楼上的都叫一维数组,还有一种赋值方式就是针对固定位置赋值。

比如我创建了一个数组叫做box3,有10个长度。但是我想给第8个位置放东西。那么就得通过数组索引下标来赋值。

int box3 [10];//声明了一个空数组,有10个位置
box[7]=100;//把第8个位置的值赋值为100,

这里为啥在【】里写7呢,因为数组下标识从0开始的,所以就是你要控制的当前位置减一就是当前是索引下标。这里只赋值了第8个位置的数,那么其他的也就是相应默认值是0;

遍历数组

也就是使用数组,数组需要遍历才能获取到数组里的值来给我们使用,当然也可以单个单个的取出来。遍历也就是通过循环来重复单个的取出来才实现的全部数据取出,否则一个数组有100个长度,要全部取出里面的东西得些100个单个取出的语句,这样很明显是不合理的吧;

这里主要是使用for循环。例如我们有个数组box4,有10个长度,当然我们给他5个数据,看全部取出来是啥结果。

#include <stdio.h>
int  main (){
int i = 0;//定义循环控制体
int box4 [10] ={1,2,3,4,5};
for (i;i<(sizeof(box4)/sizeof(box4[4]));i++){
	printf("第%d位值是:%d
",(i+1),box4[i]);
}
	return 0;
}

这里还是使用sizeof函数,但是sizeof是字节长度,因为int是占4个字节的,这里的长度10是有10个int的数,总的就是有10的4个字节的长度,所以是占用了40个字节的长度,但是我们要的是数组的长度,所以必须要÷一个字节所占的长度,这里这就随便除以一个box4集合里的一个元素即可,因为每个元素都是型嘛就是占用的4个字节

指针

指针就是地址,地址也就是指针地址就是在定义一个变量或者常量,在内存里,内存分配的空间名字,也就是地址,就像家庭地址一样,通过家庭地址就能找到你。

指针也就是一个存放地址的一个变量。可以说指针也是一种数据类型,因为是单独用来而且只能放地址的。所以创建指针和变量一样,需要先声明。但是地址这么多,在内存里也是有分类的,根据基本数据类型,指针地址分为不同的指针类型所以会见到,int类型的指针变量,double类型的指针变量。例如这个int类型的指针变量,其实是为了接收int型变量的地址,所以指针类型的变量应该和接受的数据类型地址一致。执政但是指针的值都是一样的,都是地址。可以说,不同类型的指针的值是一个类型,都叫指针类型

定义指针

用到*号,这个也就是四则运算里的乘号但是这里是作为单目运算符使用。没有这个乘号,则就和其他变量看起来差不多了。

#include <stdio.h>
int main(){
int a = 100;//定义一个局部变量a且赋初值100
int  *pa = &a;//定义一个指针pa。且将a的地址赋值给这个指针
 printf("通过指针取值:%d
",*pa);
 printf("a的值:%d
",a);
 printf("指针地址:%p
",pa);
 printf("a的地址:%p
",&a);
return 0;
}

这里会发现,通过指针取值,和a取值为啥结果一样呢?这里就是通过指针来间取值而在printf里的pa的乘号叫做取值运算符,可以这样说,定义的时候是啥样子,取值的时候直接用啥样子来写就能取到比如这里的*pa。用的乘法pa来作为一个变量名,然后要使用它的值的时候,直接用的乘法pa来取值的可能有点难懂,算了吧。知道取值的时候,要加*。因为乘法在取值的时候也是取值运算符*

这里的地址也是打印的一样的。可知道,指针的变量名字是没有乘号的,虽然我们定义的时候是*pa,但是实际上指针的名字是pa,那个乘号表示是定义的指针类型的变量,只能给他赋值地址;在打印a的地址的时候我们用到了取址运输符&,这在说&的运算符的时候讲到过。现在回忆一下&是位运算符,是将两个数换成二进制然后将都是1的记做1,其他的都是0,然后将这个对比较后的二进制换成十进制的数,这样可以产生一个中间量,可以通过这样的方式来进行两个数互换位置。在指针这里就叫做取址运算符。

声明指针

楼上的指针是声明并定义一个指针,这里的指针是有初始值的,即使a的地址,如果是只想要声明一个指针呢?看代码

#include <stdio.h>
int main(){
int a = 100;//定义一个局部变量a且赋初值100
int  *pa;//声明一个指针pa。但是这个pa
    pa= &a;//且将a的地址赋值给这个pa
 int *pb=NULL;
  printf("%p
",pa);  
  printf("%p
",pb);//000000
return 0;
}

如果一个指针在没有定义赋值,也就说只声明,然后你打印这个指针的地址,会发现会有一串乱码,即内存给的随便一个地址,这是很危险的代码。所以指针一定要赋值,就算不是使用,也要给指针赋予赋予一个NULL,当然这个NULL代表的地址是空的,而不是字符数组。这个NULL一定大写也就是所谓的空指针

判断指针类型(了解)

从语法的角度看,你只要把指针声明语句里的指针名字去掉,剩下的部分就是这个指针的类型。这是指针本身所具有的类型。让我们看看例一中各个指针的类型:

  • 1、int*ptr; : 指针的类型是 int*
  • 2、char*ptr; : 指针的类型是 char*
  • 3、int**ptr; : 指针的类型是 int**
  • 4、int(*ptr)[3]; : 指针的类型是 int(*)[3]
  • 5、int*(*ptr)[4]; : 指针的类型是 int*(*)[4]

指针所指向的类型(了解)

当你通过指针来访问指针所指向的内存区时,指针所指向的类型决定了编译器将把那片内存区里的内容当做什么来看待。

从语法上看,你只须把指针声明语句中的指针名字和名字左边的指针声明符*去掉,剩下的就是指针所指向的类型。例如:

  • 1、int*ptr; : 指针所指向的类型是 int
  • 2、char*ptr; : 指针所指向的的类型是 char
  • 3、int**ptr; : 指针所指向的的类型是 int*
  • 4、int(*ptr)[3]; : 指针所指向的的类型是 int()[3]
  • 5、int*(*ptr)[4]; : 指针所指向的的类型是 int*()[4]

数组指针

这里我们直接看后面两个字,数组指针其实是指针。下面看代码

int (*p)[3]; 

首先要了解一下运算符的优先级了,虽然读做数组指针,但是从优先级来看,首先是* p,那么则表示这是一个指针,然后再看【】,表示是一个有三位长度的数组,但是这个数组是啥类型的呢?看前面的int,说明这个数组是int型的,也就是里面的属性都是int型的数据。则这个是一个指向是int型的有3位长度的数组的指针当然这个指针的名字就是p

指针数组

看后面两个字,数组。则说明是一个数组,看代码

int *p[3]; 

【】的优先级比*高,p先和【】结合,则表示一个数组名字是p的一个数组,且长度有3位,然后结合乘号,表示这个数组里的元素是指针类型,但是为啥不是int呢?因为前面不是有个int型吗。这里要知道,楼上定义说指针的时候说过了。 指针类型是单独的一个类型,只表示地址,这个int和指针类型是没有关系的,只是表示这个指针指向的是一个int类型的变量的地址。所以这个实际上是数组。则是一个有3位长度的。是指针类型的(元素都是指针),且元素都是指向int型的指针的数组

枚举

枚举也是一个单独的类型,要使用到enum关键字,enum是小写的哈。枚举和数组类似,可以这样说。数组里是存放的变量。而枚举是存放常量的。所谓常量就不能更改初始值。也可以说枚举和数组的元素(值)是键值对。怎么说呢?枚举的键(key)则是我们定义的常量名也就是属性名。因为这里的value(值)其实是枚举语法规定好的。且第一个值的value是0即枚举的第一个元素的值永远是0

而数组,我们一般是对他的value做操作,即对数组值做操作。因为我们都是存储的数组值。但是数组的下标是从0开始的,我们也是通过下标来获取数组值,例如我们要获取box数组中的第2位的值:box[1];这也就是说,数组的key,是从0开始的,是定死的。我们操作的其实是数组值

但是枚举也是个很神奇的类型。怎么说呢?我们定义的其实就相当于键值对里的键也就key,这个value我们也是可以定义的,只不过这个value只能是整型(byte short int long)如果没有自己定义value,那么则是第一个值的value则是0,后面的依次加一。详情查看后面的枚举定义

语法:

enum 枚举类型名

{

常量1,常量2,常量3

}枚举变量名;

上面的{}里的默认常量1也就是枚举的第一个数是0

可以在定义枚举类型时改变枚举元素的值:

enum season {spring, summer=3, autumn, winter};

season:枚举类型名

没有指定值的枚举元素,其值为前一元素加 1。也就说 spring 的值为 0,summer 的值为 3,autumn 的值为 4,winter 的值为 5

枚举定义

先定义枚举类型,再定义枚举变量

enum DAY
{
      MON=1, TUE, WED, THU, FRI, SAT, SUN
};
enum DAY day;

这里的DAY是枚举类型。里面的MON,TUE等等则是变量。从这里看出,变量以及自定义类型用大写字母

  • day则是变量名字。但是DAY必须是定义好的枚举类型。
  • enum在DAY前面表示是枚举类型的DAY,这个DAY是枚举类型名,是自定义的。
  • enum DAY 在day前面表示的意思是该变量是个枚举类型变量

定义枚举类型的同时定义枚举变量

enum DAY
{
      MON=1, TUE, WED, THU, FRI, SAT, SUN
} day;

在定义枚举类型的时候就将枚举变量定义好了

省略枚举名称,直接定义枚举变量

enum
{
      MON=1, TUE, WED, THU, FRI, SAT, SUN
} day;

代码

#include <stdio.h>
 
enum DAY
{
      MON=20, TUE, WED, THU, FRI, SAT, SUN
};
 
int main()
{
    enum DAY day;
    day = WED;
    printf("%d
",day);
    return 0;
}

MON的20如果不赋值,则默认是0,这里只能赋值一个整数。

day = WED;这里是将WED的value赋值给day。则是22,因为从第一个开始往后加1.第一个是20.这个wed是第三个数,则是22;当然这里只能赋值当前美剧类型里的枚举值。否则会报错

遍历枚举

和遍历数组类似,但是需要注意,枚举值是连续的才能遍历。比如枚举值是MON=20, TUE=12, WED=12, THU, FRI, SAT, SUN这种就不是连续的。则不能使用遍历。要遍历也只能遍历WED后面的数,包括WED

假设有一个连续的枚举类型

#include <stdio.h> 
enum DAY {      MON=1, TUE, WED, THU, FRI, SAT, SUN } day; 
int main() { 
    // 遍历枚举元素    
    for (day = MON; day <= SUN; day++) {  
   			 printf("枚举元素:%d 
", (enum DAY)day);
        } 
}

通过第一数,和最后一个数,因为都是整型.直接打印++后的结果就是枚举变量的value了,打印的时候还是使用里一下转换,这里使用的是强制转换才能枚举DAY类型

原文地址:https://www.cnblogs.com/yuxiangqiezi/p/13128597.html