在C中访问对象的字节
不幸的是,我还没有找到任何类似的ISO C标准,所以我会在这里询问 在回答问题之前,请确保您熟悉指针来源的概念(请参阅和/或) 6.3.2.3(指针)第7段规定: 当指向对象的指针转换为指向字符类型的指针时, 结果指向对象的最低寻址字节。连续增量 结果,直到对象的大小,都会产生指向对象剩余字节的指针 问题是:在C中访问对象的字节,c,language-lawyer,C,Language Lawyer,不幸的是,我还没有找到任何类似的ISO C标准,所以我会在这里询问 在回答问题之前,请确保您熟悉指针来源的概念(请参阅和/或) 6.3.2.3(指针)第7段规定: 当指向对象的指针转换为指向字符类型的指针时, 结果指向对象的最低寻址字节。连续增量 结果,直到对象的大小,都会产生指向对象剩余字节的指针 问题是: “指向对象的指针”是什么意思?这是否意味着,如果我们想要得到T类型的对象的最低寻址字节的指针,我们应该将cvT*类型的指针转换为字符类型的指针,并且将从T*类型的指针获得的void类型的指
T
类型的对象的最低寻址字节的指针,我们应该将cv
T*
类型的指针转换为字符类型的指针,并且将从T*
类型的指针获得的void
类型的指针转换为void
不会给出我们想要的结果?或者“指向对象的指针”是指针的值,该指针从指针来源开始,并强制转换为void*
不会改变该值(类似于最近在C++17中的形式化)获取一个非char
c
对象并创建指向它的指针,即
int obj;
int *objPtr = &obj;
将指向对象的指针转换为指向字符的指针:
char *charPtr = (char *)objPtr;
现在,charPtr指向最低的字节或int obj。
增加它:
charPtr++;
现在它指向对象的下一个字节。依此类推,直到达到对象的大小:
int i;
for (i = 0; i < sizeof(obj); i++)
printf("%d", *charPtr++);
inti;
对于(i=0;i
指针加法的一般说明表明,对于任何值/类型的指针p
和有符号整数x
和y
,其中((ptr+x)+y)
和(x+y)
均由标准定义,(ptr+(x+y))
的行为等同于((ptr+x)+y)
。虽然可能有人会争辩说,标准没有明确规定将指针增加5倍等于增加5倍,但标准中没有任何内容表明质量实现不应该以这种方式进行
请注意,该标准的作者并没有试图将其定为“语言律师证明”。此外,他们认为没有人会关心一个明显较差的实现是否“符合要求”。与支持可靠索引的实现相比,仅在按顺序访问对象字节时才可靠工作的实现的通用性要差一些,但却没有提供任何合理的优势。因此,标准不需要强制要求支持索引,因为任何试图产生高质量实现的人都会支持它,无论标准是否强制要求它
当然,有些结构是20世纪90年代的程序员——甚至是标准的作者自己——期望高质量的编译器能够可靠地处理的,但今天一些“聪明”的编译器却没有。这是否意味着这些期望是不合理的,或者它们在应用于高质量的编译器时是否仍然准确,这是一个意见问题。在这种特殊情况下,我认为正索引应该像重复递增一样表现的含义足够强烈,我不希望编译器编写人员提出相反的观点,但我不能100%肯定没有编译器会“聪明”/迟钝到足以看到以下内容:
int test(unsigned char foo[5][5], int x)
{
foo[1][0] = 1;
// Following should yield a pointer that can be used to access the entire
// array 'foo', but an obtuse compiler writer could perhaps argue that the
// code is converting the address of foo[0] into a pointer to the first
// element of that sub-array, and that the resulting pointer is thus only
// usable to access items within that sub-array.
unsigned char *p = (unsigned char*)foo;
// Following should be able to access any element of the object [i.e. foo]
// whose address was taken
p[x] = 2;
return foo[1][0];
}
并决定它可以跳过对
foo[1][0]
的二读,因为p[x]不可能访问第一行之外的foo
的任何元素。然而,我要说的是,程序员不应该试图绕过恶意破坏者编写的编译器可能会以这种方式运行的可能性。没有一个程序能够防弹,防止破坏者编写迟钝但“符合”的编译器,程序可能被这种破坏者破坏的事实不应该被视为缺陷。“指向对象的指针”-->指向某个非功能、非void
“强制转换为void*不会改变值”几乎是正确的。编码可能会改变,但它将等同于原始编码。类似于10==10.0
,但它们有不同的编码。指针的属性与整数不同。这里有很多问题——至少7个。也许可以减少它。虽然一个理智的人可能会质疑“增量为-1”(而不是“减量为1”)的有效性,但我认为可以肯定地说,你可以按任何正数递增<代码>i+=5//这里一个愚蠢但准确的评论是“增加5”。关于你的最后一个问题,你是否特别想知道字节是否是连续的,是否可以被视为C数组,或者你的驱动方式是否不同?@zzxyz我认为你不能以任何正数递增。本标准在6.5.2.4(后缀)和6.5.3.1(前缀)中定义了增量。我认为,为标准中定义的术语创造自己的含义是不正确的。@M.M如果我理解正确,你是在试图说,省略行为的明确定义并不意味着它没有定义。好的,标准明确地声明了相反的情况,如果您更改为char*charPtr=(char*)((void*)objPtr)
,其中字符ptr
将指向?为什么?这不是对任何问题的回答。这个问题不是关于访问表示对象的字节。它询问C标准语言中的具体细节。例如,如果将指向对象的指针转换为指向void的指针,它仍然是“点”吗