如果显式给出多维数组,为什么 char[][] = {{...}, {...}} 不可能?

2024-04-04

我经历了this http://helpdoco.com/C++-C/difference-between-char-pointer-and-char-array.htm文章。我理解所解释的规则,但我想知道在定义常量多维数组并直接使用给定类型的已知值对其进行初始化时,到底是什么阻止编译器接受以下语法:

const int multi_arr1[][] = {{1,2,3}, {1,2,3}}; // why not?
const int multi_arr2[][3] = {{1,2,3}, {1,2,3}}; // OK

error: declaration of 'multi_arr1' as multidimensional array must have bounds
       for all dimensions except the first

是什么阻止编译器向右查看并意识到我们正在为每个“子数组”处理 3 个元素,或者可能仅在程序员通过的情况下返回错误,例如每个子数组的元素数量不同,例如{1,2,3}, {1,2,3,4}?

例如,在处理一维字符数组时,编译器可以查看右侧的字符串=这是有效的:

const char str[] = "Str";

我想了解发生了什么,以便编译器无法推断数组维度并计算分配的大小,因为现在在我看来编译器拥有执行此操作所需的所有信息。我在这里缺少什么?


要求编译器从初始化器推断内部维度将要求编译器以标准避免的方式追溯工作。

该标准允许初始化的对象引用自身。例如:

struct foo { struct foo *next; int value; } head = { &head, 0 };

这定义了最初指向自身的链表节点。 (推测稍后会插入更多节点。)这是有效的,因为 C 2011 [N1570] 6.2.1 7 表示标识符head“其范围在其声明符完成后开始。” A声明者是声明语法的一部分,包括标识符名称以及声明的数组、函数和/或指针部分(例如,f(int, float) and *a[3]是声明符,在声明中,例如float f(int, float) or int *a[3]).

由于 6.2.1 7,程序员可以编写以下定义:

void *p[][1] = { { p[1] }, { p[0] } };

考虑初始化器p[1]。这是一个数组,因此它会自动转换为指向其第一个元素的指针,p[1][0]。编译器知道该地址,因为它知道p[i]是一个 1 的数组void *(对于任何值i)。如果编译器不知道有多大p[i]是,它无法计算这个地址。所以,如果 C 标准允许我们写:

void *p[][] = { { p[1] }, { p[0] } };

那么编译器将不得不继续扫描过去p[1]因此它可以计算为第二个维度给出的初始值设定项的数量(在本例中只有一个,但我们必须至少扫描到}看到这一点,而且可能更多),然后返回并计算p[1].

该标准避免强迫编译器执行这种多次传递工作。要求编译器推断内部维度会违反此目标,因此标准没有这样做。

(事实上​​,我认为标准可能不需要编译器做超过有限数量的前瞻,可能在标记化过程中只需要几个字符,在解析语法时只需要一个标记,但我不确定。有些事情具有直到链接时才知道的值,例如void (*p)(void) = &SomeFunction;,但这些是由链接器填充的。)

此外,考虑一个定义,例如:

char x[][] =
    {
        {  0,  1 },
        { 10, 11 },
        { 20, 21, 22 }
    };

当编译器读取前两行初始值时,它可能需要在内存中准备数组的副本。因此,当它读取第一行时,它将存储两个值。然后它看到线端,因此它可以暂时假设内部尺寸为 2,形成char x[][2]。当它看到第二行时,它会分配更多内存(与realloc)并继续,将接下来的两个值 10 和 11 存储在适当的位置。

当它读到第三行并看到22,它实现内部维度至少为三。现在编译器不能简单地分配更多内存。它必须重新排列 10 和 11 相对于 0 和 1 在内存中的位置,因为它们之间有一个新元素;x[0][2]现在存在并且值为 0(到目前为止)。因此,要求编译器推断内部维度,同时还允许每个子数组中存在不同数量的初始值设定项(并根据整个列表中看到的初始值设定项的最大数量来推断内部维度)可能会给编译器带来大量内存移动的负担。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如果显式给出多维数组,为什么 char[][] = {{...}, {...}} 不可能? 的相关文章

  • “构建”构建我的项目,“构建解决方案”则不构建

    我刚刚开始使用VS2010 我有一个较大的解决方案 已从 VS2008 成功迁移 我已将一个名为 Test 的控制台应用程序项目添加到解决方案中 选择构建 gt 构建解决方案不编译新项目 选择构建 gt 构建测试确实构建了项目 在失败的情况
  • 以文化中立的方式将字符串拆分为单词

    我提出了下面的方法 旨在将可变长度的文本拆分为单词数组 以进行进一步的全文索引处理 删除停止词 然后进行词干分析 结果似乎不错 但我想听听关于这种实现对于不同语言的文本的可靠性的意见 您会建议使用正则表达式来代替吗 请注意 我选择不使用 S
  • Web 客户端和 Expect100Continue

    使用 WebClient C NET 时设置 Expect100Continue 的最佳方法是什么 我有下面的代码 我仍然在标题中看到 100 continue 愚蠢的 apache 仍然抱怨 505 错误 string url http
  • 不支持将数据直接绑定到存储查询(DbSet、DbQuery、DbSqlQuery)

    正在编码视觉工作室2012并使用实体模型作为我的数据层 但是 当页面尝试加载时 上面提到的标题 我使用 Linq 语句的下拉控件往往会引发未处理的异常 下面是我的代码 using AdventureWorksEntities dw new
  • 嵌套接口:将 IDictionary> 转换为 IDictionary>?

    我认为投射一个相当简单IDictionary
  • 使用实体框架模型输入安全密钥

    这是我今天的完美想法 Entity Framework 中的强类型 ID 动机 比较 ModelTypeA ID 和 ModelTypeB ID 总是 至少几乎 错误 为什么编译时不处理它 如果您使用每个请求示例 DbContext 那么很
  • 从Web API同步调用外部api

    我需要从我的 Web API 2 控制器调用外部 api 类似于此处的要求 使用 HttpClient 从 Web API 操作调用外部 HTTP 服务 https stackoverflow com questions 13222998
  • BitTorrent 追踪器宣布问题

    我花了一点业余时间编写 BitTorrent 客户端 主要是出于好奇 但部分是出于提高我的 C 技能的愿望 我一直在使用理论维基 http wiki theory org BitTorrentSpecification作为我的向导 我已经建
  • 如何使用 ICU 解析汉字数字字符?

    我正在编写一个使用 ICU 来解析由汉字数字字符组成的 Unicode 字符串的函数 并希望返回该字符串的整数值 五 gt 5 三十一 gt 31 五千九百七十二 gt 5972 我将区域设置设置为 Locale getJapan 并使用
  • C#中如何移动PictureBox?

    我已经使用此代码来移动图片框pictureBox MouseMove event pictureBox Location new System Drawing Point e Location 但是当我尝试执行时 图片框闪烁并且无法识别确切
  • 带动态元素的 WPF 启动屏幕。如何?

    我是 WPF 新手 我需要一些帮助 我有一个加载缓慢的 WPF 应用程序 因此我显示启动屏幕作为权宜之计 但是 我希望能够在每次运行时更改屏幕 并在文本区域中显示不同的引言 这是一个生产力应用程序 所以我将使用非愚蠢但激励性的引言 当然 如
  • 垃圾收集器是否在单独的进程中运行?

    垃圾收集器是否在单独的进程中启动 例如 如果我们尝试测量某段代码所花费的进程时间 并且在此期间垃圾收集器开始收集 它会在新进程上启动还是在同一进程中启动 它的工作原理如下吗 Code Process 1 gt Garbage Collect
  • 覆盖子类中的字段或属性

    我有一个抽象基类 我想声明一个字段或属性 该字段或属性在从该父类继承的每个类中具有不同的值 我想在基类中定义它 以便我可以在基类方法中引用它 例如覆盖 ToString 来表示 此对象的类型为 property field 我有三种方法可以
  • 通过指向其基址的指针删除 POD 对象是否安全?

    事实上 我正在考虑那些微不足道的可破坏物体 而不仅仅是POD http en wikipedia org wiki Plain old data structure 我不确定 POD 是否可以有基类 当我读到这个解释时is triviall
  • 如何将带有 IP 地址的连接字符串放入 web.config 文件中?

    我们当前在 web config 文件中使用以下连接字符串 add name DBConnectionString connectionString Data Source ourServer Initial Catalog ourDB P
  • 基于 OpenCV 边缘的物体检测 C++

    我有一个应用程序 我必须检测场景中某些项目的存在 这些项目可以旋转并稍微缩放 更大或更小 我尝试过使用关键点检测器 但它们不够快且不够准确 因此 我决定首先使用 Canny 或更快的边缘检测算法 检测模板和搜索区域中的边缘 然后匹配边缘以查
  • 测试用例执行完成后,无论是否通过,如何将测试用例结果保存在变量中?

    我正在使用 NUNIT 在 Visual Studio 中使用 Selenium WebDriver 测试用例的代码是 我想在执行测试用例后立即在变量中记录测试用例通过或失败的情况 我怎样才能实现这一点 NUnit 假设您使用 NUnit
  • 是否可以在 .NET Core 中将 gRPC 与 HTTP/1.1 结合使用?

    我有两个网络服务 gRPC 客户端和 gRPC 服务器 服务器是用 NET Core编写的 然而 客户端是托管在 IIS 8 5 上的 NET Framework 4 7 2 Web 应用程序 所以它只支持HTTP 1 1 https le
  • C# - OutOfMemoryException 在 JSON 文件上保存列表

    我正在尝试保存压力图的流数据 基本上我有一个压力矩阵定义为 double pressureMatrix new double e Data GetLength 0 e Data GetLength 1 基本上 我得到了其中之一pressur
  • 对来自流读取器的过滤数据执行小计

    编辑问题未得到解答 我有一个基于 1 个标准的过滤输出 前 3 个数字是 110 210 或 310 给出 3 个不同的组 从流阅读器控制台 问题已编辑 因为第一个答案是我给出的具体示例的字面解决方案 我使用的实际字符串长度为 450 个

随机推荐