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

标签 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”是什么意思?

另请参阅

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

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

最佳答案

在[基本.化合物]中:

If an object of type T is located at an address A, a pointer of type cv T* whose value is the address A is said to point to that object, regardless of how the value was obtained.

pastval 有相同的地址,因此它们指向同一个对象。一个是第一行的“最后一个元素”,第二个是第二行的第一个元素,这并不重要。该地址有一个有效的对象,因此这里的一切都是完全合理的。

<小时/>

在 C++17 中,自 P0137 起,这变化很大。现在,[basic.compound] 将指针定义为:

Every value of pointer type is one of the following:
— a pointer to an object or function (the pointer is said to point to the object or function), or
a pointer past the end of an object (5.7), or
— the null pointer value (4.11) for that type, or
— an invalid pointer value.

所以现在,past 是第二种类型的值(超出末尾的指针),但 val 是第一种类型的值(指向)。这些是不同类别的值,不具有可比性:

A value of a pointer type that is a pointer to or past the end of an object represents the address of the first byte in memory (1.7) occupied by the object or the first byte in memory after the end of the storage occupied by the object, respectively. [ Note: A pointer past the end of an object (5.7) is not considered to point to an unrelated object of the object’s type that might be located at that address. A pointer value becomes invalid when the storage it denotes reaches the end of its storage duration; see 3.7. —end note ]

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

关于c++ - 取消引用 50% 出界指针(数组的数组),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32100245/

相关文章:

c++ - 流式传输 wav 文件

c - Memcmp 用于两个具有不同数据的指针

c - 访问数组的特定元素

javascript - PHP对象数组到javascript关联数组

javascript - 在 JavaScript 中使用默认值创建自定义对象数组

c++ - 在 Windows 上使用 WaitForSingleObject 但支持 boost 线程中断

c++ - HP Fortify 分析结果,system() 命令注入(inject)

java - 同一个数组中不就是多个相同的字符串名吗?

c++ - 寻找一种方法来实现将操作作为参数的表达式

c - c编程文本文件结构和fgets中的错误