C语言结构体中的成员数组与指针的区别

简介: 无

@[TOC]

前言

1.博主实力有限,博文有什么错误,请你斧正,感谢!
2.本文借签陈皓的文章:《C语言结构体中的成员数组与指针》

问题

#include <stdio.h>
struct str{
    int len;
    char s[10];
};
struct foo {
    struct str *a;
};
int main(int argc, char** argv) {
    struct foo f={0};
    if (f.a->s) {
        printf( f.a->s);
    }
    return 0;
}
  • 请问本题错在什么地方?为什么?
  • f.a被初始化为空了嘛,用空指针访问成员变量为什么不crash(崩溃)?
  • 如果你不是太清楚,希望本片博客能对你有帮助!

NULL指针

  • NULL指针 赋值给任何指针时,其实编译器都隐含的将NULL(0)转化为对应的地址。

    struct s * p=NULL;
    这 里 NULL 隐含转化为 结构体地址。
  • NULL指针分配的分区:其范围是从 0x00000000到0x0000FFFF。这段空间是空闲的,对于空闲的空间而言,没有相应的物理存储器与之相对应,所以对这段空间来说,任何读写操作(解引用)都是会引起异常的。空指针是程序无论在何时都没有物理存储器与之对应的地址。为了保障无论何时这个条件,需要人为划分一个空指针的区域,固有上面NULL指针分区.
  • 虽然NULL指针不能进行任何解引用操作,但是进行比较或者运算是可行的。见代码

    image-20211005211035729

分析代码一

image-20211005213038354

  • 可以看出==t==的地址与==t.i==地址相同,而 ==t.p==的地址 与==t,i==的地址相差==4==字节。
  • 实际t.i,t.p的地址就是 (&t+0x00),(&t+0x04).
  • 0x00,0x04,这是i与p相对于 结构体实例的相对地址,这于结构体的内存对齐中的偏移量有关。
  • 因此 我们知道:不管结构体的实例是什么——访问其成员其实就是结构体变量的地址加成员的相对地址。
  • 但是如果t的地址恰好为 NULL呢?---

分析代码二

image-20211005214403764

  • 这里 t的地址不同于t.i的地址是因为,指针的地址和指针指向数据地址的区别。
  • 因此从代码一中我们知道,t.i的地址(&t+0x00)。但是这里 &t=0.因为 NULL指针可以进行运算,因此t->i与t->p的地址是 0x00000000,0x00000004;

结构体中的指针与数组差别

image-20211005223837441

  • 观察 汇编代码可以知道 ,(结构体中是同样道理)

    • 对于数组名来说,汇编使用的是 lea(load effective address),将地址放到寄存器中
    • 对于指针来说,汇编使用的是mov ,这是将指向的地址放带寄存器中。
  • 因此在 访问成员数组名其实得到的是数组的相对地址,而访问成员指针其实是相对地址里的内容
  • 其实就是数组名代表数组首地址,指针变量名本身代表指向数据的地址。

分析代码三

在这里插入图片描述

分析代码四

image-20211005230036539

分析前面问题

  • 请问本题错在什么地方?为什么?

    错在 printf(f.a->s).原因同代码三。

    实际就是 数组名代表数组首地址,指针变量名代表指向数据的地址。

  • f.a被初始化为空了嘛,用空指针访问成员变量为什么不crash(崩溃)?

    • 编译器会隐形的将NULL转化为 结构体的首地址。
    • 因此NULL指针可以访问成员变量时,但是只能访问成员的地址,一旦对空闲地址解引用,就会导致crash。

总结

  • 其实本篇是 数组名代表数组首元素导致,指针变量代表指向数据的地址。的另外一种解释。博主也是看完大佬陈皓文章后才发现的。大佬就是大佬!!!
相关文章
|
存储 NoSQL 编译器
【C语言】指针的神秘探险:从入门到精通的奇幻之旅 !
指针是一个变量,它存储另一个变量的内存地址。换句话说,指针“指向”存储在内存中的某个数据。
690 7
【C语言】指针的神秘探险:从入门到精通的奇幻之旅 !
|
存储 人工智能 程序员
一文彻底搞明白C语言的数组
本文详细介绍了C语言中的数组,包括定义、初始化(静态与动态)、存储方式、访问方法及常用操作,如遍历、修改元素和作为函数参数传递。数组是C语言中最基本的数据结构之一,掌握它对编程至关重要。下篇将介绍二维数组,敬请期待!
1092 0
一文彻底搞明白C语言的数组
|
存储 编译器 C语言
【C语言】指针大小知多少 ?一场探寻C语言深处的冒险 !
在C语言中,指针的大小(即指针变量占用的内存大小)是由计算机的体系结构(例如32位还是64位)和编译器决定的。
2066 9
|
安全 程序员 C语言
【C语言】指针的爱恨纠葛:常量指针vs指向常量的指针
在C语言中,“常量指针”和“指向常量的指针”是两个重要的指针概念。它们在控制指针的行为和数据的可修改性方面发挥着关键作用。理解这两个概念有助于编写更安全、有效的代码。本文将深入探讨这两个概念,包括定义、语法、实际应用、复杂示例、最佳实践以及常见问题。
757 7
|
传感器 算法 安全
【C语言】两个数组比较详解
比较两个数组在C语言中有多种实现方法,选择合适的方法取决于具体的应用场景和性能要求。从逐元素比较到使用`memcmp`函数,再到指针优化,每种方法都有其优点和适用范围。在嵌入式系统中,考虑性能和资源限制尤为重要。通过合理选择和优化,可以有效提高程序的运行效率和可靠性。
1322 6
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
711 5
|
存储 人工智能 Java
一文轻松拿捏C语言的指针的基础使用
本文介绍了C语言中的指针概念,包括直接访问和间接访问内存的方式、指针变量的定义与使用、取址运算符`&`和取值运算符`*`的应用,帮助读者深入理解指针这一C语言的核心概念。君志所向,一往无前!
560 0
|
存储 算法 程序员
C 语言指针详解 —— 内存操控的魔法棒
《C 语言指针详解》深入浅出地讲解了指针的概念、使用方法及其在内存操作中的重要作用,被誉为程序员手中的“内存操控魔法棒”。本书适合C语言初学者及希望深化理解指针机制的开发者阅读。
|
存储 程序员 编译器
C 语言数组与指针的深度剖析与应用
在C语言中,数组与指针是核心概念,二者既独立又紧密相连。数组是在连续内存中存储相同类型数据的结构,而指针则存储内存地址,二者结合可在数据处理、函数传参等方面发挥巨大作用。掌握它们的特性和关系,对于优化程序性能、灵活处理数据结构至关重要。
|
算法 C语言
C语言中的文件操作技巧,涵盖文件的打开与关闭、读取与写入、文件指针移动及注意事项
本文深入讲解了C语言中的文件操作技巧,涵盖文件的打开与关闭、读取与写入、文件指针移动及注意事项,通过实例演示了文件操作的基本流程,帮助读者掌握这一重要技能,提升程序开发能力。
1102 3