假设我有一个结构并将偏移提取到成员:
struct A {
int x;
};
size_t xoff = offsetof(A, x);
给定一个指向struct a的指针,我如何以符合标准的方式提取成员?当然,假设我们有一个正确的
结构a*
和正确的偏移量。一种尝试是这样做:
int getint(struct A* base, size_t off) {
return *(int*)((char*)base + off);
}
这可能会起作用,但是注意,例如,指针算法似乎只有在指针是同一数组的指针(或超过末尾的指针)时才在标准中定义,这不是必须的。所以从技术上来说,这种构造似乎依赖于未定义的行为。
另一种方法是
int getint(struct A* base, size_t off) {
return *(int*)((uintptr_t)base + off);
}
这可能也会起作用,但请注意,
上的算术不需要产生正确的结果(例如,我记得有些CPU具有处理非字节对齐地址的能力,这意味着数组中的每个intptr_t
不需要存在,而且据我所知,
字符
的
8步递增)。
看起来标准中有一些东西被遗忘了(或者我错过了什么)。
标准(6.5.6)只允许数组的指针算术的原因是结构可能有填充字节来满足对齐要求。所以在结构中进行指针算术确实是形式上未定义的行为。
在实践中,只要你知道你在做什么,它就会起作用。base off
不能失败,因为我们知道那里有有效的数据,并且只要它被正确访问,它就不会错位。
因此< code>(intptr_t)base off确实是更好的代码,因为不再有任何指针算法,而只有普通整数算法。因为< code>intptr_t是一个整数,所以它不是一个指针。
正如在评论中指出的,这种类型不能保证存在,它是可选的7.20.1.4/1.我想为了最大的可移植性,您可以切换到保证存在的其他类型,例如intmax_t
或ptrdiff_t
。然而,如果不支持intptr_t
的C99/C11编译器是否有用,这是有争议的。
(这里有一个小的类型问题,即< code>intptr_t是一个有符号类型,不一定与< code>size_t兼容。您可能会遇到隐式类型提升问题。如果可能的话,使用< code>uintptr_t会更安全。)
接下来的问题是*(int*)((intptr_t)base-off)
是否是定义良好的行为。关于指针转换的标准部分(6.3.2.3)规定:
任何指针类型都可以转换为整数类型。除非如前所述,否则结果是实现定义的。如果结果不能用整数类型表示,则行为未定义。结果不必在任何整数类型的值范围内。
对于这个特定的例子,我们知道这里有一个正确对齐的int
,所以它是好的。
(我也不认为存在任何指针别名问题。至少用gcc-O3-fstrict-aliasing-Wstrict-aliasing=2
编译不会破坏代码。)
根据C标准,7.19通用定义
宏是
NULL
扩展为实现定义的空指针常量;和
offsetof(*type*, *member-designator*)
它扩展到一个整数常量表达式,该表达式的类型
size_t
,其值是以字节为单位的偏移量,从结构的开头(由类型指定)扩展到结构成员(由成员指示符指定)。
因此,
偏移量()
返回以字节为单位的偏移量。
和6.2.6.1,第4段指出:
存储在任何其他对象类型的非位字段对象中的值由 n × CHAR_BIT 位组成,其中 n 是该类型对象的大小(以字节为单位)。
因为CHAR_BIT被定义为< code>char
中的位数,所以< code>char是一个字节。
因此,根据标准,这是正确的:
int getint(struct A* base, size_t off) {
return *(int*)((char*)base + off);
}
这会将基
数转换为 char *
并将字节添加到
地址。如果 off
是偏移量 (A, x);
的结果,则生成的地址是基
指向的结构 A
中 x
的地址。
你的第二个例子:
int getint(struct A* base, size_t off) {
return *(int*)((intptr_t)base + off);
}
依赖于将有符号的intptr_t
值与无符号的size_t
值相加的结果。
在 confluent kafka rest 代理中,我们可以获取特定消费者组的最后一个提交偏移量,但是我们如何获取主题的最新偏移量来计算滞后。
我在我的Spring Boot应用程序中使用KafkaListener接口,它工作得很好。偏移量由Kafka本身存储。 现在,让我们假设一个主题的消费者部署了一个新版本,并且浪费了2小时的消息。然后,他们修复了应用程序,并希望启动新版本,与两个小时前有所不同。 我可以在以前的consumer.offsetsForTimes()调用中使用consumer.seek(),但这只在使用轮询机制时是直接的
我有以下课程: SonarQube用变量标记所有三行上的错误: 移动此变量以符合Java规范约定。 如何使代码与SonarQube兼容? 我正在为Eclipse v2.6.0使用Sonarint。
如果文件很小,我就工作。但是,当文件变大时,偏移量将小于实际值。我怎样才能得到抵消?
问题内容: 将我的php版本更新到5.4.0-3后,我收到一个奇怪的PHP错误。 我有这个数组: 当我尝试像这样访问它时,会收到奇怪的警告 我真的不想只编辑我的php.ini并重新设置错误级别。 问题答案: 请尝试这种方式。…我已经测试了此代码。
问题内容: 我有一个非常特殊的问题,我试图在哪里解析 ,以便它可以给我结果 我通过使用和尝试了以下代码 但是它崩溃了 知道为什么会崩溃以及我的输出是否可以提供预期的结果吗?谢谢! 问题答案: 您的String 表示带有偏移UTC offset的 时区,因此用于解析该字符串 如果您想设置特定的时区,可以使用传递eaxmple