代码之家  ›  专栏  ›  技术社区  ›  einpoklum

在C中,当且仅当int64_t可用时才定义PRId64,这是真的吗?

  •  3
  • einpoklum  · 技术社区  · 1 年前

    我想在C中可移植地使用64位有符号类型。但是,我知道 int64_t 不能保证被定义。我可以在生成构建系统时使用一些预处理器魔法(例如CMake的 check_type_size() )获取预处理器定义,告诉我是否可以使用它。然而,我们确实有 PRId64 格式说明符,用于传递 int64_t 值到 printf() -类似的功能。因此,我可以使用 价格64 作为确定是否 int64_t 有空吗?

    2 回复  |  直到 1 年前
        1
  •  7
  •   Ian Abbott    1 年前

    您可以测试是否存在可能由提供的可选宏 <stdint.h> ,例如 INT64_MIN INT64_MAX 当且仅当相应的可选类型(如 int64_t 实施。

    根据C99§7.18第4段、C11/C17§7.20第4段和C23§7.22.1第4段:

    对于该实现提供的本文所述的每种类型, <stdint.h> 应声明typedef名称并定义相关宏。相反地对于本文所述的实现没有提供的每种类型, <stdint.h> 不得声明typedef名称,也不得定义相关宏。实现应提供描述为“必需”的类型,但可能不提供任何其他类型(描述为“可选”)。

    该标准目前不要求 PRId64 宏将不由定义 <inttypes.h> 如果 int64_t 未实现,对于由定义的其他可选类型也是如此 <stdint.h> .

    总之:

    • defined(INT64_MIN) if and only if int64_t 已实施
    • defined(PRId64) 并不意味着 int64_t 已实施
    • !defined(PRId64) 暗示 int64_t 未实现
        2
  •  3
  •   user30482    1 年前

    是的,但是。。。

    这确实是一个 代理 为了这个目的。 该标准有以下内容 <inttypes.h> 在7.8.1中:

    标题<inttypes.h>包括报头<stdint.h>并通过托管实现提供的额外设施对其进行扩展。

    这里的“托管”是指具有操作系统的系统;因此,是的,您可以使用宏来检测托管环境中相应类型的存在。请注意,C99兼容的实现 能够 定义printf和scanf格式宏,不使用 int64_t 存在(正如Ian Abbott所指出的),尽管这似乎是一个相当古怪的场景。另一方面,如果你计划在非托管环境中运行代码(或支持运行它),如嵌入式平台或内核,你不应该使用 <inttypes.h> 因为该报头可能不可用。那么,你可以用什么来代替呢?

    int64_t / uint64_t 在标准中称为“精确宽度整数”,并在7.22.2.2(C23)和7.18.1.1(C99)中定义。以下内容可以在C23标准草案的规范中找到 <stdint.h> :

    7.22.3指定宽度整数类型的宽度

    7.22.3.1概述

    任何已定义宏的每个实例都应替换为适用于以下情况的常量表达式 #如果预处理指令。其实施定义值应等于或大于 后续子条款中给出的值,除非明确指出为给定值。 一个实现应该只定义与它实际使用的typedef名称相对应的宏 提供。

    7.22.3.2精确宽度整数类型的宽度

    国际的 N _宽度精确 N
    UINT N _宽度精确 N

    在C99中,没有指定宽度宏;可以使用7.18.2.1中描述的限制宏。这些宏与7.18第4段中的C23宏有类似的警告。

    7.18.2.1精确宽度整数类型的限制

    精确宽度带符号整数类型的最小值
    国际的 N _最小值(2N 1. )
    精确宽度带符号整数类型的最大值
    国际的 N _最大值2N 1. 1.

    也就是说,您可以使用头文件中定义的宏 typedef 首先是类型。例如, INT64_WIDTH UINT64_MIN .