gpt4 book ai didi

C api同时兼容32位和64位整数

转载 作者:行者123 更新时间:2023-11-30 16:51:30 25 4
gpt4 key购买 nike

我有一个使用 int 类型的共享(或静态)库的 C api,并且想要升级到 int64_t。这样做,我想确保我以前的用户仍然可以升级该库,而不必重写他们的整个代码。

我已经根据这个要点提出了解决方案,它复制了我的代码行为(使用回调):https://git.io/vMy8G

示例.c

// User defines a different type
#define MYLONG int

#include "interface.h"
#include "stdio.h"

// User callback using his own type
int test(const int i, const my_long var, const int j) {
printf("i = %d\n",i);
printf("var = %lld\n",(long long) var);
printf("j = %d\n",j);
printf("%lld\n", 2LL*var-11);
return var - 7;
}

int main() {
// This is what user sees
api_func functionPtr = &test;
define_callback(functionPtr);

// Simulate callback call
call_callback();
return 0;
}

接口(interface).h

#pragma once

// MYLONG is defined differently internally and externally (before importing this file)
typedef MYLONG my_long;

// Callback definition
typedef int (*api_func)(const int, const my_long, const int); // surround by int to test alignment issues

void define_callback(api_func fptr);
void call_callback();

内部.c

#define MYLONG long long

#include "interface.h"

// Callback handling
api_func callback_ptr = 0;

void define_callback(api_func fptr) {
callback_ptr = fptr;
}

void call_callback() {
(*callback_ptr)(1000, 100000, 100);
(*callback_ptr)(1000, 10000000000, 100); // will overflow when user uses int
}

该库将始终使用#define MYLONG int64_t进行编译,而用户将使用#define MYLONG int64_t#define MYLONG int(这将根据其他一些设置自动完成)。最新的定义将确保向后兼容性。

Valgrind 检查所有版本均通过。

我的问题如下:

  • 安全吗?
  • 我是否依赖编译器的任何非保证行为?
  • 为什么它会(或不会)起作用? (规范中有关于此的段落吗?)
  • 您有更好的方法吗?

请注意,如果可能的话,我希望避免编写所有函数的 64 位版本。此外,这必须适用于 Linux (gcc)、Mac (gcc) 和 Windows (Visual Studio)。

最佳答案

  1. 安全吗?

没有。 example.c 中的用户将 callback_ptr 设置为:

int test(const int i, const int var, const int j)

... 和 call_callback() 调用它:

int (*api_func)(const int, const int64_t, const int)

每当 intint64_t 类型不同时,这就是 UB(不是溢出)。

  • 我是否依赖编译器的任何非保证行为?
  • 是的。

  • 为什么它会(或不会)起作用? (规范中有关于此的段落吗?)
  • 这是未定义的行为 (UB)。代码正在调用具有一个签名的函数,但该函数可能具有不兼容的签名。

  • 您有更好的方法吗?
  • 是的。
    答:当然不要使用不匹配的函数签名进行编码。
    B. 最后,我认为 OP 需要一种新的方法。我建议添加函数define_callback64(),然后让用户使用int (*f)(const)调用define_callback64() int、int64_t、const int)define_callback() 与之前一样。然后 call_callback() 可以使用设置的回调。

    <小时/>

    代码注释

    Note that I would like to avoid writing 64 bit versions of all my functions if possible.

    OP 希望“想要升级到 int64_t”但“避免编写所有函数的 64 位版本”。这是最奇怪的,而且显然是矛盾的。

    也许将internal.c重写为int64_t,然后调用select回调函数。

    typedef int (*api_func)(const int, const my_long, const int) 中的 3 个 const 没有任何作用。

    OP 似乎假设 int 是 32 位的(给定标题)。最好编写不假设这一点的代码。 int 至少 16 位。 OTOH,假设 int 不比 int64_t 宽,我认为没有什么大问题,但即使如此,C 规范也没有定义。

    OP 似乎还假设 long longint64_t 给定代码 #define MYLONG long long 但“库总是用 #define MYLONG int64_t”。 OP 需要在代码和文档中正确且一致地使用类型。

    关于C api同时兼容32位和64位整数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41750235/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com