首页 > 代码库 > 结构体语法梳理2-指针与一维数组

结构体语法梳理2-指针与一维数组

结构体指针与结构体数组

1.1 指针复习

对于指针的理解,我们一方面从语法层面上理解,一方面编译器角度理解会发生什么事情。

type  *p = value;

p+i   的结果是 value+sizeof(type)*i

对于指针变量p ,*前面的type决定了 如何通过p存储的地址去访问内存。

比如 

int  *p1 = 0x10;

char *p2 = 0x10;

double  *p3 = 0x10;

*p1 从 0x10地址处访问四个字节,并且把这四个字节的数据当int类型来看。

*p2 从0x10地址处访问一个字节,并且把这一个字节的数据当char类型来看。

*p3 从0x10地址处访问八个字节,并且把这八个字节的数据当double 类型来看,

p1+i  得到的数据是  0x10+4*i

p2+i  得到的数据是  0x10+1*i

p3+i  得到的数据是  0x10+8*i


1.2  结构体内存及访问

结构体的定义,决定了结构体成员相对于(存储结构体数据的)内存起始位置的偏移。

typedef struct{
    int num; //偏移 0字节,0-3
    int age; //偏移 4字节,4-7
    char name[10];//偏移8字节,8-17字节
}s_stu,*p_stu;

当s_stu  stu1;定义一个stu1的变量的时候,会申请 sizeof(stu1)字节的内存,假定地址为 0x10

当语法stu1.num的时候,会访问从0x10开始的4个字节。

stu1.age会访问 0x14开始的4个字节。

stu1.name[0] 会访问0x18开始的1个字节。

变量的本质是内存,变量的访问本质是读写内存,在语法层面我们看到的是变量,在机器层面,只知道内存的地址和要访问的大小。

c语言语法提供给我们通过地址去访问内存的途径。

p_stu  p = 0x10;

当p->num的时候,访问 从0x10开始4个字节

当p->age的时候,访问从0x14开始4个字节

当p->name[0]的时候,访问从0x18开始1个字节

这样能访问的前提是 从 0x10开始的 sizeof(s_stu)个字节内存是合法有效的。

内存本身是没有类型的,描述内存的两个要素是地址跟大小,我们通过语法决定了访问这快内存的方式,假定0x10地址开始100个字节都是合法有效的,那么我可以读取1个字节看做char类型数据,也可以读取4个字节看做int数据,也可以读取sizeof(s_stu)看做s_stu 的数据。

---------------------------------------------------------------------------------------------------------------------------------------------

在C语言里面要得到合法有效的内存,要么定义变量,要么 malloc系列函数申请。

p_stu p = (p_stu)malloc(sizeof(p_stu));

malloc申请sizeof(s_stu)个字节的内存,刚好能存储一个学生的信息,所以如下操作是没有问题的。

p->num = 1;
p->age = 2;
strcpy(p->name,"lilei");

这个等同于 

s_stu  stu1;
p_stu p = &stu1;
p->num = 1;
p->age = 2;
strcpy(p->name,"lilei");

只不过访问的内存区域不同而已。

1.3  结构体数组与指针

其实会使用数组和指针以及结构体体了,这个知识点只是一个综合应用。

(1)数组基本使用

int  a[10];

a[i] 可以访问第i个元素,为int.

s_stu b[10];

b[i]可以访问第i个元素,为s_stu;

b[i].age = 1;
b[i].num = 2;
strcpy(b[i].name,"lilei");

(2)一维数组与指针关系

int  *p1 = a;

p_stu *p2 = b;

p存储的是a[0]的地址,数组的本质是连续的内存,数组的每个元素是相邻的,根据指针加减法 ,p1+i 是a[i]的地址。

可以通过 *(p1+i) 来访问a[i],又有等式 *(p1+i)= p1[i],所以也可以通过p[i]来访问a[i]。

套用上面关系:

b[i].age 可以用如下几种方式访问:

(p2+i)->age ;
(*(p2+i)).age;
p[2].age;
(3) 写完整代码测试

#include <stdio.h>
//结构体指针与数组
typedef struct student{
	int num; //成员
	int age;
	char name[10];
}stu,*pstu;
int main(int argc,char** argv)
{
	/*
		依然是 a[i] = *(a+i)
		注意 如果是地址 则用 ->  是变量则用 . 
		不确定优先级的时候加上()
		可分别注释下面代码,打印去验证。
	*/
	stu a[10];
	int i = 0;
	pstu p = a;

	for(i = 0;i<10;i++)
	{
			//1
			a[i].num = 1;
			a[i].age = 2;
			strcpy(a[i].name,"stui");	
			//2	
			(*(a+i)).num = 1;
			(*(a+i)).age = 1;
			strcpy((*(a+i)).name,"stui");
			//3
			(a+i)->num = 1;
			(a+i)->age = 1;
			strcpy((a+i)->name,"stui");
			//4
			p[i].num = 1;
			p[i].age = 2;
			strcpy(p[i].name,"stui");	
			//5		
			(*(p+i)).num = 1;
			(*(p+i)).age = 1;
			strcpy((*(p+i)).name,"stui");
			//6		
			(p+i)->num = 1;
			(p+i)->age = 1;
			strcpy((p+i)->name,"stui");
			
	}
	for(i = 0;i<10;i++)
	{
		printf("age = %d,",a[i].age);
		printf("num = %d,",a[i].num);
		printf("name =%s,",a[i].name);	
	}
	return 0;
	
}


(4)指针变量自增

指针加减搞定了以后,其实用指针变量自增就很好理解了:

p = a;

for(i = 0;i<10;i++)
{
     (*p).age = 1;
      p->num = 1;
  p++;
}
注意循环完毕后,p已经不是存储a[0]的地址了

画内存图增加理解