我知道遗产总是一个理由,但我想看看mariadb的这个例子,看看我是否足够理解它来批判正在发生的事情,
static int show_open_tables(THD *, SHOW_VAR *var, char *buff) {
var->type = SHOW_LONG;
var->value = buff;
*((long *)buff) = (long)table_cache_manager.cached_tables();
return 0;
}
在这里他们正在接受 char*
他们写信给 var->value
这也是一个 char*
. 然后它们强制指针指向 buff
并将类型设置为a SHOW_LONG
以此表示。
我想知道为什么他们会用 char*
但不是为了这个 uintptr_t
--尤其是当它们强制指针指向long和其中的其他类型时。
不是以前的标准吗- uintptr_t
使用 void*
对于c++中的多态性?
2条答案
按热度按时间wnavrhmk1#
他们接受char*,并将其写入var->value,这也是char*。然后他们强制一个指针指向buff中的long,并将类型设置为show\u long以指示它。
或者别的什么。那密码太可怕了。
我想知道为什么他们会使用char*,而不是uintptru\t——特别是当他们强制指针指向long和其他类型时。
谁知道呢?谁知道那家伙写这首歌的时候在看什么?谁在乎呢?那代码太可怕了,我们当然不应该试图从中吸取教训。
在c++中,使用void*表示多态性不是一种规范吗?
是的,现在仍然是。目的
uintptr_t
是定义一个大到足以容纳指针的整数类型。我想看看mariadb的这个例子,看看我是否理解得足够好,可以对发生的事情提出批评
你可能对这样做有所保留,但我当然没有,那个api只是一个明目张胆的谎言。方法(如果你必须这样做的话)显然是:
}
那么至少它不再是一颗滴答作响的定时炸弹了。
嗯,好吧,也许(只是也许)这个函数在某个分派表中使用,因此需要(除非您强制转换它)有一个特定的签名。如果是这样的话,我肯定不会翻一万行代码去找出答案(不管怎样,我也做不到,时间太长了,我的平板电脑崩溃了)。
但如果有什么,那只会让事情变得更糟。现在定时炸弹变成了隐形轰炸机。不管怎样,我一刻也不相信。这只是一个危险的废话。
jk9hmnmh2#
这里似乎有两个问题。所以我把答案分成两部分。
使用char*
使用
char*
很好。字符类型(char
,signed char
,和unsigned char
)被c和c标准特别处理。c标准定义了访问对象的以下规则:对象的存储值只能由具有以下类型之一的左值表达式访问:
与对象的有效类型兼容的类型,
与对象的有效类型兼容的类型的限定版本,
与对象的有效类型相对应的有符号或无符号类型,
与对象的有效类型的限定版本相对应的有符号或无符号类型,
在其成员中包含上述类型之一的聚合或联合类型(递归地包括子聚合或包含的联合的成员),或
一种字符类型。
这实际上意味着字符类型是最接近的标准来定义一个'字节'类型(
std::byte
在c中,17定义为enum class byte : unsigned char {}
)但是,根据上述规则
char*
到long*
然后分配给它是不正确的(尽管在实践中通常是有效的)。memcpy
应该改用。例如: