程序设计分组训练实验一

news/2024/9/20 10:19:50

实验一必备知识

csdn-vs调试

[bilibili生成目录word]
https://www.bilibili.com/video/BV1V14y1t73F/?share_source=copy_web&vd_source=668d4d374b623b9a00fbe541e1b24f78

数组指针退化

数组名一旦充当地址,就会退化!!!

  1. 数组名作为函数参数传递时
    • 当把数组名作为函数参数传递给函数时,数组名会退化为指向数组首元素的指针。例如:
    void func(int arr[]) {// 这里的arr实际上是一个指针,等价于int* arr
    }int main() {int a[5];func(a);return 0;
    }
    
    • 在这个例子中,amain函数中是一个数组名,代表整个数组。但是当它被传递给func函数时,a就退化为一个指向int类型的指针(int*),在func函数内部,arr不再具有数组的长度信息等数组特性,仅仅是一个指针。
  2. 使用取地址运算符&取数组名的地址(取整个数组的地址)之外的情况
    • 在表达式中,如果数组名不是取整个数组的地址(&数组名)的情况,数组名都会退化为指向首元素的指针。例如:
    int a[5];
    int* p=a; // 这里a退化为指向首元素的指针,所以可以赋值给int*类型的p
    
    • 另外:
    int a[5];
    sizeof(a); // 这里a表示整个数组,结果为5 * sizeof(int)
    
    • 但是如果写成:
    int a[5];
    int* p = a;
    sizeof(p); // 这里p是指针,结果为sizeof(int*)
    

sizeof()是操作符,不会引发数组退化

sizeof是一个编译时操作符,它的作用是获取操作数所占用的字节数。当操作数是数组名时,sizeof会将数组名视为整个数组对象,而不是指向数组首元素的指针。
在 C 语言中,数组的大小是其类型的一部分。例如,对于int a[5];,数组a的类型是int[5],这个类型信息在编译时是确定的。
当计算sizeof(a)时,编译器根据数组的定义直接计算出整个数组所占用的字节数,即5 * sizeof(int)(假设sizeof(int)为 4 字节,那么sizeof(a)为 20 字节)。

关于数组名

1. 对于二维数组int a[4][4]

  • 从数组的存储角度来看,二维数组在内存中是按行顺序存储的,a可以看作是一个指向包含4个int元素的数组的指针(即a的类型是int(*)[4])。

2. 分析*a + 1

  • 根据运算符优先级,*的优先级高于+
  • 首先,*a等价于a[0],它是指向数组a的第一行(即a[0]是一个包含4个int元素的数组,在这里它会退化为指向该数组首元素的指针,类型为int*)。
  • 那么*a+1就是在a[0]的基础上偏移一个int类型的单位。如果a的起始地址为0x1000(假设),a[0]的值也是0x1000(因为a[0]是第一行数组的首地址),*a + 1的值就是0x1000 + sizeof(int)(假设sizeof(int)=4,则值为0x1004),它指向了a[0][1]这个元素。

3. 分析*(a + 1)

  • 这里a+1表示将指针a(类型为int(*)[4])向下移动一行(因为指针的偏移量是sizeof(int[4]))。如果a的起始地址为0x1000a+1的值就是0x1000+sizeof(int[4]) = 0x1000 + 16(假设sizeof(int)=4),它指向了数组a的第二行(即a[1])。
  • 然后*(a + 1)就等价于a[1],它是一个包含4个int元素的数组,同样会退化为指向该数组首元素的指针(类型为int*),它指向a[1][0]这个元素。

()和[]

[]优先级高于()

  1. 对于(*(a + 2))[3]
    • 根据C语言中数组和指针的运算规则:
      • a是一个二维数组名,它可以被看作是一个指向数组(这个数组包含4个int元素)的指针。
      • a+2表示将指针a向后移动2个“单位”,这里的“单位”是指包含4个int元素的数组的大小。所以a + 2指向二维数组a中的第三行(行索引从0开始)。
      • *(a + 2)就是取a+2所指向的那一行数组。
      • 最后(*(a + 2))[3]表示取这一行数组(也就是第三行)中的第4个元素(列索引从0开始),在给定的初始化中a[2][3]=12
  2. 对于*(a + 2)[3]
    • 根据运算符优先级,先计算(a + 2)[3]
      • (a+2)是一个地址,(a + 2)[3]等价于*((a + 2)+3)。这表示将a + 2这个地址再向后移动3个“单位”(每个单位是包含4个int元素的数组的大小),然后取这个地址指向的内容。实际上,这是越界访问,因为原始的二维数组a只有4行,这样的计算导致访问到了非法的内存区域。
      • 然后再对这个非法访问得到的结果进行间接访问(*操作),由于访问的是非法内存,所以得到的是一个未定义的值,这里显示为-858993460,这个值是完全不可预测的,不同的编译器、不同的运行环境可能会得到不同的结果。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/62439.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

关于api接口详解大全

API接口,即应用程序编程接口(Application Programming Interface),是一组预定义的函数或协议,它允许不同的软件应用程序之间进行交互。API在现代软件开发中扮演着至关重要的角色,它促进了不同系统之间的集成和通信,为开发者提供了强大的工具来构建更加高效、安全和创新的…

Amazon Bedrock 模型微调实践(二):数据准备篇

本博客内容翻译自作者于 2024 年 9 月在亚马逊云科技开发者社区发表的同名博客: “Mastering Amazon Bedrock Custom Models Fine-tuning (Part 2): Data Preparation for Fine-tuning”亚马逊云科技开发者社区为开发者们提供全球的开发技术资源。这里有技术文档、开发案例、技…

Spark(一)概述

基本概念Spark是一种基于内存的快速、通用、可扩展的大数据分析计算引擎Spark vs HadoopSpark和Hadoop的根本差异是多个作业之间的数据通信问题:Spark多个作业之间数据通信是基于内存,而Hadoop是基于磁盘Hadoop Spark类型 分布式基础平台, 包含计算, 存储, 调度 分布式计算工…

基于语义增强的少样本检测,突破新类别偏见 | ICIP24

Few-shot目标检测(FSOD)旨在在有限标注实例的情况下检测新颖对象,在近年取得了显著进展。然而,现有方法仍然存在偏见表示问题,特别是在极低标注情况下的新颖类别。在微调过程中,一种新颖类别可能会利用来自相似基础类别的知识来构建自己的特征分布,导致分类混淆和性能下…

如何解决Warning: include(): Failed opening file_path for inclusion问题

解决方法检查文件路径确认文件路径是否正确无误,包括路径中的每个目录和文件名。验证文件是否存在使用file_exists()函数检查文件是否真的存在于指定路径上。检查文件权限确认文件具有足够的权限供当前用户读取。可以使用chmod命令修改文件权限:bashchmod 644 file_path确认文…

如何解决Unknown column column_name in field list问题

当遇到 "Unknown column column_name in field list" 这类错误时,通常表明 SQL 查询中引用了一个不存在的列。这类错误通常会给出具体的列名和出错的位置。下面是一些详细的解决步骤: 解决方法:检查 SQL 查询:确认 SQL 查询中引用的列名是否正确。检查拼写错误或…

最小圆覆盖(html)

最小圆覆盖问题是什么呢?就是指在二维平面上有一堆点,然后我们要求一个最小半径的圆能够将所有点全部都包住,这就是最小圆覆盖问题。 最小覆盖圆的性质 性质1:最小覆盖圆是唯一的 证明:我们假设有两个圆O1,O2,他们半径都是r,都是最小覆盖圆,那么所有的点一定在两圆的…

如何解决You have an error in your SQL syntax

当遇到 "You have an error in your SQL syntax" 这类错误时,通常表明 SQL 语句存在语法错误。这类错误通常会给出具体的错误位置和可能的原因。下面是一些详细的解决步骤: 解决方法:查看错误提示:错误提示通常会显示具体的 SQL 语句和出错的位置。例如: You ha…