结构体语法梳理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]的地址了

画内存图增加理解

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

时间: 2024-10-14 10:32:10

结构体语法梳理2-指针与一维数组的相关文章

C#调用C++ 平台调用P/Invoke 结构体--含有内置数据类型的一维、二维数组、字符串指针【六】

[1]结构体中含有内置数据类型的一维数组 C++代码: typedef struct _testStru3 { int iValArrp[30]; WCHAR szChArr[30]; }testStru3; EXPORTDLL_API void Struct_ChangeArr( testStru3 *pStru ) { if (NULL == pStru) { return; } pStru->iValArrp[0] = 8; lstrcpynW(pStru->szChArr, L&quo

指针知识梳理2-指针与一维数组

一.一维数组复习 数组的本质是连续的内存,我们可以通过一下代码验证. int main() { int a[10]; int i; for(i = 0;i<10;i++) { printf("%p\n",&a[i]); } } 打印出每个元素的地址,会发现地址间隔是4 ,这个间隔刚好等于sizeof(int). 那么如果知道了a[0]的地址,我们就可以通过地址的加减算出a[i]的地址,然后访问a[i]; 二.通过指针访问一维数组 指针能够访问一维数组的两个前提是: 1.内

C语言结构体中的函数指针

这篇文章简单的叙述一下函数指针在结构体中的应用,为后面的一系列文章打下基础 本文地址:http://www.cnblogs.com/archimedes/p/function-pointer-in-c-struct.html,转载请注明源地址. 引言 指针是C语言的重要组成部分, 于是深入理解指针并且高效地使用指针可以使程序员写出更加老练的程序.我们要记住指针是一个指向内存地址的变量.指针可以引用如int.char……常见的数据类型,例如: int * intptr; // 声明一个指向整型值的

结构体知识梳理4-浅拷贝深拷贝

应用场景分析,我们希望对一个学生的信息做备份 代码一 typedef struct student{ int num; int age; char name[10]; }s_stu,*p_stu; //stu1 stu2 有独立的内存空间,存储 num age name s_stu stu1; s_stu stu2; stu1.num = 1; stu1.age = 1; strcpy(stu1.name,"lilei"); //以下做的是memcpy(&stu2,&s

结构体中定义函数指针

转自:http://blog.csdn.net/unix21/article/details/9293877 结构体指针变量的定义,定义结构体变量的一般形式如下: 形式1:先定义结构体类型,再定义变量 struct结构体标识符 { 成员变量列表;… }; struct 结构体标识符 *指针变量名; 变量初始化一:struct结构体标识符 变量名={初始化值1,初始化值2,…, 初始化值n }; 形式2:在定义类型的同时定义变量 struct结构体标识符 { 成员变量列表;… } *指针变量名;

C/C++结构体语法总结

结构体简介结构体属于聚合数据类型的一类,它将不同的数据类型整合在一起构成一个新的类型,相当于数据库中一条记录,比如学生结构体,整合了学号,姓名等等信息.结构体的好处就是可以对这些信息进行整体管理操作,类似面向对象中类的属性,有了结构体,我就可以更好抽象描述一个类别,个人感觉类就是由结构体发展而来的.在C/C++中,结构体声明的关键字为struct. C语言结构体语法第一种语法表示struct 结构体名称{    数据类型 member1:    数据类型 member2; }; 这种方式在声明结

柔性数组(结构体最后一个域为0/1数组)

结构体最后的长度为0或1数组的作用(转载) 2012-05-07 17:07:09 其实很 早在看LINUX下就看到这个东西,后来在MFC内存池里同样也看到了类似的东西,还依照MFC写过一个类似的小内存池,(MFC用的是return this + 1)后来在李先静的<系统程序员成长计划>里看到了类似的定义,于是心里想着总结一下,结果发现网上已经有牛人总结的很好了,于是乎就转了过来,谢谢你们 的分享,这是我前进的动力!同时,需要引起注意的:ISO/IEC 9899-1999里面,这么写是非法的,

C艺术篇 3-1 指针与一维数组(1)

我们先来看指针与一维数组的关系,例题如下: 从输出结果得知,arr是数组名,它是指针常量,而ptr是指针变量. arr表示此数组第一个元素的地址,即arr等同于&arr[0]. arr可以使用指针变量的*表示符号,如*arr等同于arr[0],*(arr+1)等同于arr[1],依次类推. 在2-1中介绍过 int *ptr = &x; 其实是下列两条语句的组合 int *ptr; ptr = &x; 可以理解为 ptr就是地址,当本题将数组地址给ptr时候, 把ptr当为数组,所

结构体,内存,指针例题.DOC

2015.1.30 递归函数:1.自身调用自己:2.要有结束条件!typedef 后面加分号:一般后面的重定义名加_,例如:typedef unsigned long int uint_16;结构体成员存放是不重叠的,但是结构体变量内存会重叠,可以节省内存空间! 字节对其对cpu运行效率有影响.底层的时候要注意这个问题有效对齐:min(自身对齐,指定对齐)结构体自身对齐:max(成全自身对齐)圆整:结构体自身对齐 % 有效对齐 == 0: int a[10] = {....} 后面的是初始化表,