【问题标题】:C++ array accessingC++ 数组访问
【发布时间】:2013-05-15 14:54:48
【问题描述】:

假设我有:

int test[10];

在 32 位机器上。如果我这样做了:

int b = test[-1];

显然,在访问数组(越界)时这是一个很大的禁忌,但实际发生了什么?只是好奇

我是在访问数组“之前”的 32 位字吗?

int b = *(test - 1);

或者只是解决一个非常遥远的单词(从“测试”内存位置开始)?

int b = *(test + 0xFFFFFFFF);

0xFFFFFFFF是十进制-1的二进制补码表示

【问题讨论】:

  • 这是未定义的行为。
  • @alex23:这也是 C99 中未定义的行为。您链接到的问题中的答案并不矛盾,这些答案同样适用于 C++。

标签: c++ arrays indexing addressing


【解决方案1】:

当您尝试访问数组边界之外的元素时,程序的行为未定义。

可能发生的情况是:假设您有一个 32 位 int 类型,您在 test[0] 之前访问堆栈上的 32 位内存(如果有)并将其转换为一个 int。您的进程甚至可能不拥有此内存。不好。

【讨论】:

    【解决方案2】:

    无论发生什么,你都会得到未定义的行为,因为指针算法只定义在一个数组中(包括最后一个位置)。

    一个更好的问题可能是:

    int test[10];
    int * t1 = test+1;
    int b = t1[-1];      // Is this defined behaviour?
    

    答案是肯定的。下标(C++11 5.2.1)的定义是:

    表达式 E1[E2] 与 *((E1)+(E2)) 相同(根据定义)

    所以这相当于*((t1)+(-1))。指针加法的定义(C++11 5.7/5)是针对所有整数类型,有符号或无符号的,所以什么都不会导致-1转换为无符号类型;所以表达式等价于*(t1-1),因为t1-1 在数组边界内,所以它是明确定义的。

    【讨论】:

      【解决方案3】:

      C++ 标准说它是未定义的行为并且是非法的。这在实践中意味着任何事情都可能发生,并且任何事情都可能因硬件、编译器、选项以及您能想到的任何其他事情而有所不同。由于任何事情都可能发生,因此推测特定的硬件/编译器组合会发生什么并没有多大意义。

      【讨论】:

        【解决方案4】:

        官方的回答是行为未定义。非正式地,您试图在数组开始之前访问整数。这意味着您指示计算机计算数组开头之前 4 个字节的地址(在您的情况下)。此操作是否成功取决于多种因素。其中一些是数组是否将分配在堆栈段或静态数据段上,具体来说该地址的位置将在哪里。在通用机器(windows/linux)上,您可能会得到一个垃圾值,但如果地址恰好位于进程无权访问的某个地方,它也可能导致内存冲突错误。任何人都可以猜测专用硬件上可能发生的事情。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-06-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-09-30
          相关资源
          最近更新 更多