当前位置: 首页 > 知识库问答 >
问题:

使用FFIsize_tprintf

司空叶五
2023-03-14

为了用printf在C中打印一个size_t整数,转换格式器是%zu

但是,当我将printf%zu一起使用时,通过FFI printzu而不是整数调用Haskell中的C函数。怎么解决呢?

文件zu. c

#include <stdio.h>

void printzu(){
    size_t x = 666;
    printf("x=%zu", x);
}

模块库。hs

{-# LANGUAGE ForeignFunctionInterface #-}
module Lib
  where
import Foreign

foreign import ccall unsafe "printzu" printzu' :: IO ()
Prelude> import Lib
Prelude Lib> printzu'
x=zu

共有3个答案

越星晖
2023-03-14

我想提供另一种方法来处理不符合C99/C11标准但提供64位或更宽类型的系统。

导入并包含stdint。h/int类型。h设计用于将旧系统连接到新的C99标准。

示例:C99标准力。h头和MS Visual Studio

然后通过它们强制转换为一种广泛的类型

#if SIZE_MAX > ULONG_MAX
// Include from the standard location or wherever the imported included files are saved.
#include <stdint.h>
#include <inttypes.h>

void printzu(){
    size_t x = 666;
    printf("x=%" PRIuMAX "\n", (uint_max_t) x);
}

#else
void printzu(){
    size_t x = 666;
    printf("x=%lu\n", (unsigned long) x);
}
#endif
柏高洁
2023-03-14

当未实现“%zu”时,另一种方法是转换为某个宽类型并打印该类型,但有一定的截断风险。

size_t sz = foo();
printf("%lu\n", (unsigned long) sz);  // risk of truncation.

代码可以尝试其他整数宽的类型,如uintmax_t无符号长,但是如果"%zu"没有实现,那么很可能"%ju""%llu"也不会实现被执行。

部分打印可以避免截断。

printf("%lX%08lX\n", 
    (unsigned long) (sz/0x10000u/0x10000u), (unsigned long) (sz & 0xFFFFFFFFu));

// remote truncation risk remains.
printf("%lu%09lu\n", 
    (unsigned long) (sz/1000000000u), (unsigned long) (sz%1000000000u));

可以使用更复杂的代码来避免前导数字。

姬乐
2023-03-14

由于printf()是C标准库的一部分,它通常在一些运行库中实现。当动态链接时,如果根据调用代码的进程的不同,链接了库的不同版本,则可能会对相同的代码产生这种效果。如果%zu不起作用,那么它是一个旧版本,目前还不支持C99。

在windows上,它很可能是系统的MSVCRT. DLL,不再用于公共用途,但与旧的MS Visual C 6版本保持兼容。例如,默认情况下,MinGW链接到该库,因此您不需要运送自己的C运行时。这当然有限制库函数为C89/C90的缺点。

打印一个size_t通常比较安全方法是将其转换为无符号长并打印:

size_t x = 666;
printf("x=%lu", (unsigned long)x);

这只会给出错误的结果,如果

  • 实际上,平台的大小\u t大于无符号长(这是正确的,例如,对于采用LLP64数据模型的64位系统,如win64)和
  • 您在运行时确实有一个不适合无符号long的大小。该值必须至少大于4G(232),因为这是无符号长的保证最小范围

请注意,演员阵容在这里非常重要。因为printf()是一个可变函数,所以原型看起来就像printf(const char*fmt,…) ,因此编译器没有可用的类型信息——因此无法进行自动转换。

如果问题特别是MSVCRT。如果您想坚持使用C99或更高版本,我建议使用inttypes。h在前面的回答中。这将永远不会在Windows上打印错误的值(并且在其他平台上仍然需要符合C99标准的库)。

 类似资料:
  • 有没有办法在使用 jongo 查询 MongoDB 时添加 ?我发现这样的错误 - '排序超出了 104857600 字节的内存限制,但没有选择加入外部排序。正在中止操作。传递 allowDiskUse:true 可以选择加入,可以通过以下方式阻止,您的聚合看起来像 但据我所知,Jongo 中的类仅将管道应用于自身,然后您可以使用 方法执行。 是否有任何方法可以将该参数传递给mongo而不从Jon

  • 问题内容: 我在远程服务器上有一个管理Web应用程序。该应用程序是使用MEAN堆栈编写的,我列出了连接到Web应用程序所需的所有RESTful路由。 我正在编写一个Java客户端应用程序,该应用程序需要从该管理应用程序发送和接收数据。如果我具有服务器的IP地址和REST路由,如何将客户端连接到Web应用程序? 我想我需要提供到服务器和REST API文件的URL连接,然后仅调用诸如和的路由功能。

  • 问题内容: 我使用spring数据和方法来获取模型。调用此方法时如何使用查询提示? 上面的源代码工作正常,但是我不能为我的JPA提供程序(在我的情况下为EclipseLink)设置QueryHint。 以上是我使用spring-data使用查询提示的方式, 我还发现了这个尚未解决的问题。 问题答案: 当我想使用spring-data创建查询时,请遵循上述算法。 1)是否已经提供的查询 通过弹簧数据

  • 我使用spring数据和方法获取模型。调用此方法时如何使用查询提示 上面的源代码运行良好,但我无法为我的JPA提供者(在我的例子中是EclipseLink)设置QueryHint。 我使用spring数据使用查询提示的方式如下:, 我也发现这个还没有解决。

  • 通过io的requestAbs方法调用/调用/使用REST API的vertx实现。vertx。果心http。vertx-core-3.2.0中的HttpClient类。jar导致HTTP错误::302,响应数据为HTML Erro响应。 不确定requestAbs方法的行为,因为没有引发异常,也没有写入任何日志。此外,还随附了使用vertx JAR的此方法的源代码。如果方法实现有bug,是否有问

  • 问题内容: 说我有: 我该如何使用表单外部的“提交”按钮提交该表单,我认为在HTML5中有一个“提交”的动作属性,但是我不确定那是否是完全跨浏览器的,如果不是这样的话,做这个? 问题答案: 一个对我来说很好的解决方案,在这里仍然缺少。它需要具有目视隐藏或元件whithin的,和相关的它元件外部。它看起来像这样: 现在,此链接使您可以通过单击元素来“单击”表单元素。