【问题标题】:Are array memory addresses always in the order of least to greatest?数组内存地址是否总是按从小到大的顺序排列?
【发布时间】:2015-07-04 06:06:54
【问题描述】:

当我用指针算术和!=做一个过程时,比如

template <typename T> void reverse_array ( T * arr, size_t n )
{
    T * end = arr + n; 
    while (arr != end && arr != --end) 
    {
         swap(arr,end);
         ++arr;
    }
}

我总是非常小心,因为如果我写错了我的程序,那么在极端情况下,第一个指针可能会“跳过”第二个指针。但是,如果数组是这样的

&arr[0] < &arr[1] < ... < &arr[n]

对于任何长度为n-1 的数组arr,那么我不能做类似的事情

template <typename T> void reverse_array ( T * arr, size_t n )
{
    T * end = arr + n;
    if (arr == end) break;
    --end;
    while (arr < end)
    {
        swap(arr,end);
        ++arr; --end;
    }
}

因为它更具可读性?还是有危险迫在眉睫?内存地址不只是整数类型,因此可以与&lt; 媲美吗?

【问题讨论】:

  • 我建议您在其他地方执行--end,而不是作为while 语句的停止条件的一部分。它将使您的代码更具可读性,并有助于避免对 end 在该条件内以及循环本身内的值的怀疑。如果您确实需要在语句中测试这两个条件,请使用end-1(并在循环内部递减它)。
  • 是的,它有效。我不知道 n 应该是什么,但如果你想要下一个元素,你最好使用 +1。

标签: c++ arrays pointers


【解决方案1】:

关系运算符被定义为在比较同一数组中的地址时正确工作(事实上,还有类类型的对象,其中也有一些关于内存布局的保证),包括过去的指针。

但是,如果您“跳过”数组结尾指针,则不再比较同一数组中的两个地址,并且行为未定义。 (一个原因是,当您在对象外部进行指针运算时,您实际上可能会遇到回绕,但 UB 不受限制)。

关于跳转,您的情况完全没问题,因为您的 end 指针不是数组的最后一个,因为您总是至少执行一个 --end--end 移出数组的空数组将是一个问题,但您需要单独测试。

结论:您的第二个代码完全有效。

【讨论】:

    【解决方案2】:

    对于 C(因为您同时标记了两者),是的,它们可以在同一个数组中进行比较:

    当比较两个指针时,结果取决于所指向对象在地址空间中的相对位置。如果两个指向对象类型的指针都指向同一个对象,或者都指向同一个数组对象的最后一个元素,它们比较相等。如果指向的对象是同一个聚合对象的成员,则指向稍后声明的结构成员的指针比较大于指向结构中较早声明的成员的指针,并且指向具有较大下标值的数组元素的指针比较大于指向同一数组的元素的指针具有较低的下标值。所有指向同一联合对象成员的指针比较相等。如果 表达式P 指向数组对象的一个​​元素,而表达式Q 指向同一个数组对象的最后一个元素,指针表达式Q+1 比较大于P。在所有其他情况下,行为是未定义的。

    -- C11 6.5.8,“关系运算符”。

    但这并不是因为它们“只是整数类型”,它们不是(和aren't guaranteed to be represented as in memory)——而是因为它们也有为它们定义的行为。

    【讨论】:

      猜你喜欢
      • 2017-06-23
      • 1970-01-01
      • 2014-10-31
      • 2016-08-31
      • 2013-07-12
      • 1970-01-01
      • 2012-09-08
      • 2020-06-20
      • 2015-01-17
      相关资源
      最近更新 更多