【问题标题】:Using itoa() results in: "assignment makes pointer from integer without a cast"使用 itoa() 会导致:“赋值使指针从整数不进行强制转换”
【发布时间】:2011-06-23 03:25:59
【问题描述】:

我正在用 C 语言编写 BCD(二进制编码十进制)并负责编写不同的 bcd 函数。

我需要将整数 i 编码为大小为 n 的缓冲区 char *s。该函数在成功时返回 0,在溢出时返回 -1(编码 i 需要大于 n 的缓冲区)。

这里是函数:int bcd_encode(int i, int n, char *s)

和一个示例输入:assert(bcd_encode(a, 128, s) == 0);

我正在编写函数 bcd_encode 的代码,如果我错了,请纠正我,但我相信一个函数,并且只有在你有一些 func(char x[]) 和 char func(char *x) 时才相信一个函数,它们是同一回事?因此,您可以将它们都视为 char 数组。如果它在函数定义之外,char x[]; 将是一个字符数组,char *x; 将是一个指针。

int bcd_encode(int i, int n, char *s){  
    int j = 0;  
    s = itoa(i, s, n+1);  
}

但这会返回一个警告“赋值使指针从没有强制转换的整数”和 itoa 的未定义符号。我尝试了几种不同的变体

*s = itoa(i); s = itoa(i); s = itoa(i, s, n+1);

任何帮助将不胜感激。提前致谢!

【问题讨论】:

  • 也许你想在函数结束时返回一个int
  • itoa 仅适用于 MSVC++ (AFAIK)。这不是标准的 C。
  • 它不是标准的 C,但已被广泛实施。

标签: c string type-conversion integer prototype


【解决方案1】:

你说:

...如果我错了,请纠正我,但我相信一个函数,并且只有在你有一些 func(char x[]) 和 char func(char *x) 时才相信一个函数,它们是相同的事物?因此,您可以将它们都视为 char 数组。如果它在函数定义之外 char x[];将是一个 char 数组和 char *x;将是一个指针。

最好将它们都视为函数内部的指针(而不是数组),但是您已经掌握了关键点 - 在函数参数列表中,数组和指针之间的区别是模糊的,但在其他地方指针和数组不同。

在代码中,由于假定itoa() 在没有相反信息的情况下返回一个整数,因此您不能将其存储在指针中或作为指针(不使用大锤强制转换,这会使您的代码损坏)。

itoa() 返回什么?它不是标准的 C 函数(如在 ISO/IEC 9899:1999 中,也不在 POSIX 中)。 Wikipedia 建议它不返回任何值,因此您不应该在任何地方分配它的值。 Linux 将其作为<stdlib.h> 中的非标准扩展,具有返回char *(这是其第二个参数的值)的不同接口。您可以放心地忽略返回值;实际上,您也可以进行分配(在包含标题之后),但分配是无操作的。您确实需要知道该函数是非标准的,它有多种定义,因此您必须了解什么对您的平台是正确的,或者避免使用它(也许改用snprintf())。


引用链接的 Linux 手册页:

char* itoa (int __val, char * __s, int __radix)

将整数转换为字符串。

函数 itoa() 将整数值从 val 转换为将存储在 s 下的 ASCII 表示。调用者负责在 s 中提供足够的存储空间。

注意:
缓冲区 s 的最小大小取决于基数的选择。例如,如果基数是 2(二进制),您需要提供一个最小长度为 8 * sizeof (int) + 1 个字符的缓冲区,即每个位一个字符加上字符串终止符一个字符。使用较大的基数将需要较小的最小缓冲区大小。 警告:
如果缓冲区太小,则存在缓冲区溢出的风险。 使用基数作为基数进行转换,基数可以是 2(二进制转换)到 36 之间的数字。如果基数大于 10,则 '9' 之后的下一个数字将是字母 'a'。

如果 radix 为 10 且 val 为负数,则会在前面加上减号。

itoa() 函数返回作为 s 传递的指针。

您不想使用n+1 作为基数。

【讨论】:

  • 啊,谢谢你在第一部分纠正我。我相信itoa() 会返回 char 值。
  • 与其相信事情,不如去查查。你会因此而高兴得多,你的雇主、奶牛工人和客户也会如此。
【解决方案2】:
#include <stdlib.h>

如果没有包含,编译器对itoa()一无所知,并假定它返回一个int

【讨论】:

  • 嗯我有 stdio.h 而不是 stdlib 但它仍然会出错(所以我会继续挖掘)
  • 它不是标准的 C,因此 #include 位置可能会有所不同。请参阅您的系统/编译器的文档。
【解决方案3】:

函数成功返回 0 或 溢出时为 -1(编码 i 需要大于 n 的缓冲区)。

而你并没有这样做。

int j = 0;

这是干什么用的?

s = itoa(i, s, n+1);

你为什么要分配给 s?

我尝试了几种不同的变体 来自

*s = itoa(i); s = itoa(i); s = itoa(i, s, n+1);

随机尝试,直到你偶然发现一个可行的方法并不是一种好的编程方法。

这里分配给 s 或 *s 是不合适的,表明对 C 的理解很差;我强烈建议获得更多的语言指导。完成后,您可以使用 snprintf,例如,

#include <stdio.h>
int bcd_encode(int i, int n, char *s){  
    int r = snprintf(s, n, "%d", i);
    return r < n? 0 : -1;  
}

假设 s 应该是 NUL 终止的,并且 n 包括 NUL - 这些细节没有在您的描述中指定。

顺便说一句,这不是“BCD”的意思——见http://en.wikipedia.org/wiki/Binary-coded_decimal

【讨论】:

    【解决方案4】:

    itoa() 未定义意味着您缺少头文件

     #include <stdlib.h> 
    

    如果未定义,则编译器假定未知函数 itoa() 返回一个 int(出于愚蠢的历史原因)。

    始终听取编译器警告 - 他们是你的朋友!

    【讨论】:

    • 我一直在学习更多地倾听编译器错误。即使我添加了 它仍然给我同样的错误......我认为这是我的 char *s
    • 这意味着您没有 itoa() - 检查您的编译器文档,您可能有类似名称的东西,例如。 _itoa()
    猜你喜欢
    • 2013-06-05
    • 1970-01-01
    • 2013-12-14
    • 2011-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-06
    • 1970-01-01
    相关资源
    最近更新 更多