C语言 数组-结构体-指针

变量

变量是计算机这存储的数据,并且这个数据是可以变化的。但数据并不是直接存放在内存中,而是先申请内存空间(按照变量的类型申请一个合适大小的空间),然后将变量值放入空间中。
int a = 5;

int a;
a = 5;等价,都是先申明一个int空间,int占用4个字节的内存,然后再将"5"存储到这个4个字节中。

int main(void)
{ 
	printf("%d\n",sizeof(int));//占4个字节
	printf("%d\n",sizeof(float));//占4字节
	printf("%d\n",sizeof(double));//占8字节
	printf("%d\n",sizeof(char));//占1字节
	printf("%d\n",sizeof(long int));//占8字节
}

输出结果为:
C语言 数组-结构体-指针_第1张图片

数组

概念

数组可以存储一个固定大小的相同类型元素的顺序集合。数组是用来存储一系列数据,但它往往被认为是一系列相同类型的变量。
数组的声明并不是声明一个个单独的变量,比如 number0、number1、…、number11,而是声明一个数组变量,比如 numbers,然后使用 numbers[0]、numbers[1]、…、numbers[11] 来代表一个个单独的变量。数组中的特定元素可以通过索引访问。
所有的数组都是由连续的内存位置组成。
C语言 数组-结构体-指针_第2张图片
申明12个int型空间,即申请了12个4字节的空间。这12个字节的地址是连续的(在指针部分再介绍)。

数组的初始化

数组的初始化是指,在创建数组的同时给数组的内容一些合理初始值(初始化)。例如:
int arr1[10] = {1,2,3};(数组中有10个元素,前三个元素初始化为1,2,3 后面剩下的7个元素全部默认为0) int arr2[] = {1,2,3,4};(数组中有多少个元素由初始化的内容决定,数组中有4个元素)
char型同理。

结构体

定义

结构体是由一批数据组合而成的一种新的数据类型。组成结构型数据的每个数据称为结构型数据的“成员”。例如:

typedef struct
{
    char name[10];
    int age;
    char sex[3];
} mate;

一结构体内可定义多个、多种变量,每个变量为该结构体的成员。
mate为结构体名,mate的用法类似于int、char。

	mate class1;
		
	printf("%s",class1.name);
	printf("%d",class1.age);
	printf("%s",class1.sex);

申明结构体后,该变量就有了地址空间,就可以进行正常的运算或赋值。

联合体

	//联合体,可以有多个变量,但同时只有一个生效,因为成员使用的地址为同一块,有一个赋值时,其他值会被覆盖。
union ID {
	int age;
	char name[12];
};

指针

定义

通过访问变量的内存空间的过程叫做间接访问。
指针也是一种数据类型,但只用于存放其他变量的内存地址。指针又分为:整数指针,浮点数指针,字符指针,函数指针,数组指针,指针的指针。

int * //指向整数类型的指针
float * //指向浮点数类型的指针
char * //指向字符类型的指针

	int a = 5;
	int * p;
	
	p = &a[0];
	//或者p = a;
	printf("%x\n",p);
	printf("%d\n",a);
	printf("%d\n",*p);

输出结果
C语言 数组-结构体-指针_第3张图片
由图知,变量a存放在0X19FF2C地址里,一个字节为一个地址,int型为4个字节,即指针p指向的a的第一个字节的地址。

指针的运算规则

  1. 两个指针不能做加法,但可以做减法,且减法只能是大地址减小地址。
    原因:a地址为0X19FF2C,b的地址为0X19FF3E,两个地址相加,得到一个新地址,但是新地址与ab毫无关联,但相减就可以得到a与b之间相差多少个字节,若用一个数组的尾地址减去头地址,即得到整个数组做占用的字节数。
  2. 指针加减n
    p+n:表示p指向地址加上n*sizeof§,若是int型,则为p+4n,char型为p+n;
    减法同理。
	int a[5] = {5,10,12,15,20};
	int * p;
	
	p = &a;
	printf("%x\n",p);
	printf("%d\n",*p);
	printf("%x\n",p+1);
	printf("%d\n",*p+1);
	printf("%d\n",*(p+1));

输出结果:
C语言 数组-结构体-指针_第4张图片
p是地址,p是该地址上存储的值,p+1即为该地址加上1sizeof(int),*p+1表示运算(p地址的值加上1),
(p+1)是只p+1sizeof(int)该地址上的值。

由于数组的地址是连续的,则a[0]的地址是0x19ff1c到0x19ff1f,共四个字节,a[1]的地址是0x19ff20到0x19ff23,同样也是4个字节。就有p+1,这个地址刚好为a[1]的地址,就有*(p+1)对应了a[1]的值。这就完成了一维数组的地址操作。
多维数组的指针操作及指向指针地址的指针操作下次再补充。

链表

	typedef struct tagbook {
	int num;
	char title[30];
	struct tagbook *next;
}Book;

int main(void)
{
	Book *bk[5];
	Book *pk;
	char tmp[30];
	//创建5个结构体并给初值
	//申请内存
	for (int i = 0; i < 5; i++) {
		bk[i] = (Book*)malloc(sizeof(Book));
		bk[i]->num = i+1;
		sprintf(tmp, "book %d", i+1);
		strcpy(bk[i]->title,tmp);
	}
	//将5个结构体按照自己的顺序连接
	bk[0]->next = bk[4];
	bk[4]->next = bk[2];
	bk[2]->next = bk[1];
	bk[1]->next = bk[3];
	bk[3]->next = NULL;
	//用一个指针将其打印出来
	pk = bk[0];
	while (pk != NULL) {
		printf("%d %s\n", pk->num, pk->title);
		pk = pk->next;
	}
	//释放内存
	for (size_t i = 0; i < 5; i++) {
		free(bk[i]);
	}

	system("pause");
	return 0;
}



输出结果为
C语言 数组-结构体-指针_第5张图片

你可能感兴趣的:(C,指针)