首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >可同时兼容32位和64位整数的c api

可同时兼容32位和64位整数的c api
EN

Stack Overflow用户
提问于 2017-01-19 19:37:52
回答 2查看 167关注 0票数 1

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

我已经在这个gist上找到了一个解决方案,它复制了我的代码行为(使用回调):https://git.io/vMy8G -

example.c

代码语言:javascript
复制
// 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

代码语言:javascript
复制
#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();

internal.c

代码语言:javascript
复制
#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 (这将根据其他设置自动完成)。最新的定义将确保向后兼容。

所有的建筑都通过了瓦伦的检查。

我的问题如下:

  • 安全吗?
  • 我是否依赖编译器的任何无保证行为?
  • 为什么它会(或不会)起作用?(规范中有关于这一点的段落吗?)
  • 你看到更好的方法了吗?

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

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-01-25 14:51:02

  1. 安全吗?

不是的。C中的用户将callback_ptr设置为:

代码语言:javascript
复制
int test(const int i, const int var, const int j)

..。call_callback()将其称为:

代码语言:javascript
复制
int (*api_func)(const int, const int64_t, const int)

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

  1. 我是否依赖编译器的任何无保证行为?

是。

  1. 为什么它会(或不会)起作用?(规范中有关于这一点的段落吗?)

它是未定义的行为(UB)。代码调用一个带有一个签名的函数,但是该函数可能有一个不兼容的函数。

  1. 你看到更好的方法了吗?

是。

当然不要用错误匹配的函数签名来编码.

最后,我认为OP需要一种新的方法。我建议添加一个函数define_callback64(),然后让用户像以前一样用int (*f)(const int, int64_t, const int)define_callback()调用define_callback64()。然后,call_callback()可以使用设置的那个。

代码注释

请注意,如果可能的话,我希望避免编写所有函数的64位版本。

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

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

3 const in typedef int (*api_func)(const int, const my_long, const int)没有任何用途。

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

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

票数 0
EN

Stack Overflow用户

发布于 2017-01-19 19:41:45

要编写最好的移植代码,最好的方法就是不要依赖于大小。如果您确实显式地使用了uint32_tint64_t

否则使用本机intlong

请求用户为完全不必要的东西定义宏是容易出错的。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41750235

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档