取消引用50%的出界指针(数组数组)

时间:2015-08-19 15:49:44

标签: c++ c arrays pointers language-lawyer

这是我在“我不理解C和C ++中的指针”集合中的一个新问题。

如果我将具有相同值的两个指针的位混合(指向相同的存储器地址),则恰好具有完全相同的位表示,当一个是可解除引用且一个是超过结束时,标准说什么会发生什么?

#include <stdio.h>
#include <string.h>
#include <assert.h>

// required: a == b
// returns a copy of both a and b into dest 
// (half of the bytes of either pointers)
int *copy2to1 (int *a, int *b) {
    // check input: 
    // not only the pointers must be equal
    assert (a == b);
    // also the representation must match exactly
    int *dest;
    size_t s = sizeof(dest);
    assert(memcmp(&a, &b, s) == 0); 

    // copy a and b into dest:
    // on "exotic" architectures, size does't have to be dividable by 2
    size_t half = s/2; // = floor(s/2), 
    char *pa = (char*)&a, *pb = (char*)&b, *pd = (char*)&dest;

    // copy half of a into dest:
    memcpy (pd, pa, half);
    // copy half of b into dest:
    memcpy (pd+half, pb+half, s-half); // s-half = ceil(s/2)

    //printf ("a:%p b:%p dest:%p \n", a, b, dest);    

    // check result
    assert(memcmp(&dest, &a, s) == 0);
    assert(memcmp(&dest, &b, s) == 0);

    return dest;
}

#define S 1 // size of inner array

int main(void) {
    int a[2][S] = {{1},{2}};
    int *past = a[0] + S, // one past the end of inner array a[0]
        *val = &a[1][0], // valid dereferenceable pointer
        *mix = copy2to1 (past, val);
    #define PRINT(x) printf ("%s=%p, *%s=%d\n",#x,x,#x,*x)
    PRINT(past);
    PRINT(mix);
    PRINT(val);
    return 0;
}

我真正想要理解的是:“p指向对象x”是什么意思?

另见

这个问题是我之前关于数组数组问题的更好的版本:

以及有关指针有效性的其他相关问题:

2 个答案:

答案 0 :(得分:9)

在[basic.compound]中:

  

如果T类型的对象位于地址A,则指向类型 cv T*的指针,其值为   地址A据说指向该对象,无论获得的值如何

pastval具有相同的地址,因此它们指向同一个对象。一个人过去的时间并不重要&#34;第一行和第二行是第二行的第一个元素。该地址有一个有效的对象,所以这里的一切都是完全合理的。

在C ++ 17中,从P0137开始,这种情况发生了很大的变化。现在,[basic.compound]将指针定义为:

  

指针类型的每个值都是以下之一:
   - 指向对象或函数的指针(指针指向指向对象或函数),或者
   - 一个超过对象(5.7)末尾的指针,或者    - 该类型的空指针值(4.11)或
   - 无效指针值

现在,past是第二种类型的值(超过结尾的指针),但val是第一种类型的值(指向)。这些是不同类别的价值观,无法比较:

  

作为指向或超过对象末尾的指针的指针类型的值表示对象占用的内存(1.7)中的第一个字节的地址或占用存储结束后的内存中的第一个字节由对象分别。 [注意:超过对象末尾的指针(5.7)不被视为指向可能位于该地址的对象类型的无关对象。当指示的存储达到其存储持续时间的末尾时,指针值变为无效;见3.7。 -end note]

past并不指向某些内容,因此将其内容视为与val相同,不再具有意义。

答案 1 :(得分:3)

  

我真正想要理解的是:“p指向对象x”意味着什么。

对象p包含一个值,该值对应于内存中对象x的位置。

就是这样。这就是它的意思。你似乎决心让它变得比它需要的更复杂。

指针类型不是算术类型,并不意味着像这样随意。通过在左值上使用一元&运算符,使用不是sizeof或一元&运算符的操作数的数组表达式或调用库函数来获取有效指针值返回指针值。

除此之外的所有(大小,表示,物理与虚拟等)都是实施细节,并且实施时广泛它来代表地址。这就是为什么标准不会说任何关于当你用指针值玩Frankenstein博士时会发生什么。

如果您非常熟悉平台的寻址约定(虚拟和物理),并且您知道实现如何在内存中布置项目以及它如何表示指针类型,并且您有有效用例以这种方式破解你的指针值,然后破解你的内心 - 语言标准对这个主题都没有任何说法。