【发布时间】:2015-11-13 00:47:37
【问题描述】:
这是我的“我不理解 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”是什么意思?
另见
这个问题是我之前关于数组数组的问题的一个更好的版本:
- Is memcpy of a pointer the same as assignment? 这是我另一个问题的变体:
- Dereferencing an out of bound pointer that contains the address of an object (array of array)
以及其他关于指针有效性的相关问题:
【问题讨论】:
-
@JohnBode "这让我头疼" 我希望如此。想到这里,我的脑袋都快要爆炸了,现在我希望每个人都有同样的感受。
-
您能否补充一下使您相信标准委员会应该定义当您将两个指针混合在一起时会发生什么的原因?或者你只是在这里讨厌 C 和 C++ 吗?
-
".. C 和 C++ 有问题。... 炒作..." 没问题。那是两种(不同的顺便说一句)语言的持续发展。它们并没有被宣传为可移植的程序集,它们在不牺牲两者都提供的高级抽象的情况下与您目前可以获得的一样可移植。哎呀,至少它们是标准化的,据我所知,这不适用于 Java、C#、Python、Ruby、Go、Rust、JavaScript(尽管有 ECMA)、BASIC 方言,...
-
是的,我确实读过它。我为什么要关心一种或另一种方式?这是一个糟糕的代码,在实际程序中没有位置。让语言律师讨论它的有效性,同时我们凡人无论如何都应该避开这种结构。如果您认为此类问题正在扼杀 C 和 C++,那么您需要更加努力地思考。
-
@curiousguy 是的。您对两种不同的语言提出相同的问题。这条规则的重点是,许多人标记垃圾邮件 C 和 C++ 以吸引更多观众,但随后对 C 答案不感兴趣,因为他们使用 C++ 或其他方式编程。这就是为什么我对标记为 C 和 C++ 的问题非常敌对的原因。只有询问 C 和 C++ 之间的差异或交互的问题才应同时标记。
标签: c++ c arrays pointers language-lawyer