struct 结构体中 数组和指针

本文深入探讨了在结构体中对数组和指针进行初始化与赋值的关键细节,包括数组与指针的区别、初始化注意事项以及赋值过程中的常见错误与解决方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文主要介绍在struct 结构体中对数组和指针的操作细节。

 

我们需要明确两个概念:

a、  初始化:分配内存并写入值。

b、  赋值:  查找内存并写入值。

 

   在上一篇文章有提到数组和指针的初始化和赋值问题,对于数组,可以初始化,但不能对整个数组赋值,而指针,可以初始化也可以赋值。

 

   在结构体中,数组和指针最大的的区别为:数组将信息存在结构体所占有的内存中,而指针是将信息的首地址保存在结构体所占有的内存中,例如:

   typedef  struct name{

      char a[20];

      char *p;

}Name;

Name A={“Llilonglin”,“Llilonglin”};

结构体对象A中的数组会将字符串常量“Lilonglin”COPY到A的存储内存中,而A中的指针只保存字符串常量在静态常量存储区中的首地址。

 

在结构体中对数组的初始化和赋值有以下需要注意:

一、赋值

例如 定义结构体对象

     Name A;

在使用时,编译器将会为该结构体分配内存空间,但为对结构对象A的变量初始化。 此时只能通过赋值操作来写入值。在对数组a[10]的赋值时应谨慎,例如:

A.              A.a[10]=”Lilonglin”, gcc将给出警告 :“赋值时将指针赋给整数,未作类型转换”,该警告主要由两个原因引起:1、 “.”结构体成员运算符的作用是访问结构体中个成员,该处操作的是结构体变量A中数组的第10个元素,虽然该下标已经越界;2、“Lilonglin”在此处编译器理解为一个常指针,指针是不能直接赋值给字符变量的。

B.               A.a=“Lilonglin”,gcc将会提示错误:赋值时,类型不兼容。 在定义申明完数组后数组名具有常量特性,表示数组存储空间的开始地址,而C语言中不能对常量赋值。

C.              根据数组的特性,如果需要得到对数组的正确赋值,则需要对数组的每个元素进行对应赋值。在此不再举例。

二、初始化

在结构体初始化时,用字符串对数组的初始化也需要有注意的地方,例如:

A、        Name A={.a=”Lilonglin”}  //OK

B、         1:Name A={.a[10]=”Lilonglin”}  //error  gcc提示:初始化数组索引越界。

2:Name A={.a[9]=”Lilonglin”}  //right  printf(“%s”,A.a) 得到“Lilonglin”

3:Name A={.a[1]=”Lilonglin”}  // right  printf(“%s”,A.a) 得到“Lilonglin”

            为什么在1中,指定初始化用a【10】时,gcc会提示越界呢。 在编译的过程中,在语法扫错阶段GCC的对数组边界检查时,发现了该错误,从而给出了提示,在VC下则不会,在此不得不佩服GCC的严谨。

从2和3我们可以看到当使用不同的下标时对数组的初始化完全没有影响,

这不得不怀疑在结构体中,用字符串对数组的初始化时只与数组名有关,因为数组名具有指针属性,之后数组的各个元素被初始化,读者可以打印某个数组元素试试。

      此处只讨论了用字符串初始化的情况,对非字符串时指定初始化时,下标将起作用,大家可以试一试

### C语言结构体指针数组结构体数组指针的区别 #### 定义上的区别 在C语言中,**结构体指针数组**是一个指向多个不同结构体实例的指针集合,而**结构体数组指针**则是指向整个结构体数组的一个单一指针。 - **结构体指针数组**:这是一个普通的数组,其中每个元素都是一个指向特定类型的结构体指针。 示例定义如下: ```c struct Test { char cdata; int idata; }; struct Test obj1 = {'A', 1}; struct Test obj2 = {'B', 2}; struct Test* ptrArray[2]; ptrArray[0] = &obj1; ptrArray[1] = &obj2; ``` - **结构体数组指针**:这是单个指针,它指向的是由连续存储的一系列相同类型结构体组成的数组的第一个元素。 示例定义如下: ```c struct Test arrayObj[2] = { {'X', 10}, {'Y', 20} }; struct Test (*ptrToArray)[2] = &arrayObj; ``` --- #### 访问方式的不同 对于这两种不同的数据形式,在访问其内部成员的方式上也存在差异: - 对于**结构体指针数组**,通过索引来获取对应的指针并间接访问目标对象的内容。 ```c printf("%c %d\n", (*ptrArray[0]).cdata, (*ptrArray[0]).idata); // 输出 A 1 printf("%c %d\n", ptrArray[0]->cdata, ptrArray[0]->idata); // 同样效果,更简洁写法 ``` - 而针对**结构体数组指针**来说,则需先解除对该数组整体地址的引用再进一步操作具体位置的数据项。 ```c printf("%c %d\n", (*(ptrToArray))[0].cdata, (*(ptrToArray))[0].idata); // 输出 X 10 printf("%c %d\n", (*ptrToArray)[1].cdata, (*ptrToArray)[1].idata); // 输出 Y 20 ``` 上述两种方法均实现了对相应字段值的有效读取[^1]。 --- #### 存储布局对比 从内存分配角度来看两者也有显著差别: - 当声明了一个`struct Test* ptrArray[N];`这样的结构体指针数组时,实际上只是预留了一片能够容纳N个指针大小的空间,并未自动初始化这些指针所指向的具体实体;因此还需要手动为其赋初值使其真正关联到有效的结构体实例上去才行。 - 反观像这样定义出来的结构体数组指针:`struct Test(*ptrToArray)[M]=&someStructArray;`,这里已经明确了这个变量实际代表的就是某个已存在的含有M个元素规模之下的结构体数组首址信息而已. --- #### 应用场景分析 基于以上特性描述可以得出它们各自适用场合的大致范围: - 如果程序设计需求涉及到频繁更换或者动态调整各个独立个体间相互关系的话那么采用「结构体指针数组」会更加灵活便捷一些因为只需要简单修改对应下标的指向即可完成重新配置工作无需顾虑底层物理排列顺序等问题. - 假设当前任务重点在于高效处理大批量同质化记录单元并且希望保持原有线性序列不变的情况下选用「结构体数组指针」往往能带来性能优势由于减少了额外层次跳跃动作从而加快存取速度同时简化逻辑控制流程便于维护管理. ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值