解引用一个超出边界50%的指针(数组的数组)
Dereferencing a 50% out of bound pointer (array of array)
这是我的"我不理解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=%dn",#x,x,#x,*x)
PRINT(past);
PRINT(mix);
PRINT(val);
return 0;
}
我真正想理解的是:"p指向对象x"是什么意思?
参见
这个问题是我之前关于数组的数组的问题的一个更好的版本:
- 是一个指针的内存相同的分配?这是我另一个问题的变体:
- 解引用一个包含对象(数组的数组)地址的超出绑定的指针
和其他有关指针有效性的问题:
- 指针变量只是整数与一些操作符或他们是"神秘的"?
- 和c++问题:用相同类型的对象覆盖一个对象
In [basic.compound]:
如果类型为
T
的对象位于地址A
,则使用类型为cvT*
的指针,其值为地址A
被认为指向该对象,,而不管该值是如何获得的。
past
和val
有相同的地址,所以它们指向同一个对象。一个是第一行的"过了最后一个",第二个是第二行的第一个元素,这并不重要。在那个地址有一个有效的对象,所以这里的一切都是完全合理的。
在c++ 17中,从P0137开始,这改变了很多。现在,[basic.compound]将指针定义为:
指针类型的每个值都是下列值之一:
-指向对象或函数的指针(据说该指针指向对象或函数),或
- 指针超过对象的末尾(5.7),或者
-该类型的空指针值(4.11),或
- 无效的指针值。
所以现在,past
是第二种类型的值(指针经过结束),但val
是第一种类型的值(指针指向)。这些是不同类别的值,不可比较:
指针类型的值是指向或超过对象结束的指针,分别表示该对象占用的内存(1.7)的第一个字节的地址,或该对象占用的存储结束后的第一个字节的地址。[注:指针经过对象的末尾(5.7)不被认为指向可能位于该地址的与该对象类型无关的对象。当指针所指向的存储达到其存储期限时,指针值将失效;见3.7。
past
没有指向任何东西,因此将其内容视为与val
相同不再有意义。
我真正想理解的是:"p指向对象x"是什么意思。
对象p
包含一个值,该值对应对象x
在内存中的位置。
就是这样。这就是它的全部含义。你似乎执意要把事情弄得更复杂。
指针类型不是算术类型,不能像那样任意修改。通过在左值上使用一元&
操作符、使用不是一元sizeof
或一元&
操作符的操作数的数组表达式,或调用返回指针值的标准库函数,可以获得有效的指针值。
除此之外的一切(大小、表示、物理vs虚拟等)都是实现细节,当涉及到表示地址时,实现差异很大。这就是为什么标准没有说任何关于当你用指针值扮演弗兰肯斯坦博士时会发生什么。
如果您非常熟悉您的平台的寻址约定(包括虚拟的和物理的),并且您知道您的实现如何在内存中布局项以及它如何表示指针类型,并且您有一个有效的用例来以这种方式破解指针值,那么您可以随心而为—两种语言标准都没有在这个主题上说什么。
- std::数组边界检查如何工作?
- 在哪种情况下,C++会在编译时进行数组边界检查?
- 分段错误发生在索引离开C++数组边界之后
- 使用 auto 时不检查数组边界
- 数组边界外的指针
- 为什么 gcc 即使请求也不抱怨数组边界?
- 将索引超出数组边界在 C++ 中的内核之前抛出异常或错误
- C++ - 最快的检查数组边界
- 使用硬件内存保护对64位硬件进行数组边界检查
- 比较器获取C++中数组边界之外的索引
- 在C++中使用映射而不是数组来保护在数组边界之外的搜索
- 警告:数组下标高于数组边界 [-Warray-bounds]
- c++中的动态分配不检查数组边界
- 如何在c++中管理数组边界
- STL push_back优化导致数组下标在数组边界之上
- 如何在模板中正确设置和传入数组边界(在c++中)
- Xcode是否可以防止c++数组边界运行时问题?
- 数组边界溢出
- 使用std::vector和.at()检查2D数组边界
- 我可以走到数组边界之外