为什么要将指针作为(char*)传递并强制转换为(long*)

kq4fsx7k  于 2021-06-24  发布在  Mysql
关注(0)|答案(2)|浏览(374)

我知道遗产总是一个理由,但我想看看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++中的多态性?

wnavrhmk

wnavrhmk1#

他们接受char*,并将其写入var->value,这也是char*。然后他们强制一个指针指向buff中的long,并将类型设置为show\u long以指示它。
或者别的什么。那密码太可怕了。
我想知道为什么他们会使用char*,而不是uintptru\t——特别是当他们强制指针指向long和其他类型时。
谁知道呢?谁知道那家伙写这首歌的时候在看什么?谁在乎呢?那代码太可怕了,我们当然不应该试图从中吸取教训。
在c++中,使用void*表示多态性不是一种规范吗?
是的,现在仍然是。目的 uintptr_t 是定义一个大到足以容纳指针的整数类型。
我想看看mariadb的这个例子,看看我是否理解得足够好,可以对发生的事情提出批评
你可能对这样做有所保留,但我当然没有,那个api只是一个明目张胆的谎言。方法(如果你必须这样做的话)显然是:

static int show_open_tables(THD *, SHOW_VAR *var, long *buff) {

  var->type = SHOW_LONG;
  var->value =  (char *) buff;
  *buff = (long)table_cache_manager.cached_tables();
  return 0;

}
那么至少它不再是一颗滴答作响的定时炸弹了。
嗯,好吧,也许(只是也许)这个函数在某个分派表中使用,因此需要(除非您强制转换它)有一个特定的签名。如果是这样的话,我肯定不会翻一万行代码去找出答案(不管怎样,我也做不到,时间太长了,我的平板电脑崩溃了)。
但如果有什么,那只会让事情变得更糟。现在定时炸弹变成了隐形轰炸机。不管怎样,我一刻也不相信。这只是一个危险的废话。

jk9hmnmh

jk9hmnmh2#

这里似乎有两个问题。所以我把答案分成两部分。

使用char*

使用 char* 很好。字符类型( char , signed char ,和 unsigned char )被c和c标准特别处理。c标准定义了访问对象的以下规则:
对象的存储值只能由具有以下类型之一的左值表达式访问:
与对象的有效类型兼容的类型,
与对象的有效类型兼容的类型的限定版本,
与对象的有效类型相对应的有符号或无符号类型,
与对象的有效类型的限定版本相对应的有符号或无符号类型,
在其成员中包含上述类型之一的聚合或联合类型(递归地包括子聚合或包含的联合的成员),或
一种字符类型。
这实际上意味着字符类型是最接近的标准来定义一个'字节'类型( std::byte 在c
中,17定义为 enum class byte : unsigned char {} )
但是,根据上述规则 char*long* 然后分配给它是不正确的(尽管在实践中通常是有效的)。 memcpy 应该改用。例如:

long cached_tables = table_cache_manager.cached_tables();
memcpy(buf, &cached_tables, sizeof(cached_tables));
``` `void*` 这也是一个合理的选择。是否更好是意见的问题。我认为最清晰的选择是为 `char` 传达将其用作字节类型的意图(例如。 `typedef char byte_t` ). 在我的脑海中,虽然我能想到几个著名的图书馆使用 `char` 按原样,按字节类型。例如,boost内存Map文件代码给出 `char*` 和leveldb使用 `std::string` 作为字节缓冲区类型(可能是为了利用sso)。

### 关于uinptr\t: `uintptr_t` 是一个可选类型,定义为能够容纳指针的无符号整数。如果要将指向的对象的地址存储为整数,那么它是一种合适的类型。这不是一个适合在这里使用的类型。

相关问题