在C语言中将整型转换为字符数组

9

在C语言中,是否可以仅通过强制类型转换将int类型转换为“string”类型?不使用任何函数,如atoi()sprintf()吗?

我想要的效果如下:

int main(int argc, char *argv[]) {
    int i = 500;
    char c[4];

    c = (char)i;
    i = 0;
    i = (int)c;
}

原因是我需要生成两个随机整数(0到500),并将它们作为一个字符串发送到另一个进程的消息队列中。另一个进程接收该消息并执行LCM。
我知道可以使用 atoi() 和 itoa() 来完成。但我的老师要求只使用强制转换。
此外,为什么以下代码无法编译?
typedef struct
{
    int x;
    int y;
} int_t;

typedef struct
{
    char x[sizeof(int)];
    char y[sizeof(int)];
} char_t;

int main(int argc, char *argv[])
{
    int_t rand_int;
    char_t rand_char;

    rand_int.x = (rand() % 501);
    rand_int.y = (rand() % 501);

    rand_char = (char_t)rand_int;
}

9
好的,我会尽力为您翻译。以下是需要翻译的内容:关键词是“我的老师想要”,这意味着之后的所有内容都由您决定如何翻译,我们不会给出任何提示。微笑 - K Scott Piel
你无法想象我为尝试做到这一点所浪费的大量精力、时间和研究。一切都运行正常,只是转换不起作用。 - Bodosko
6
我认为你没有浪费一秒钟时间......你做了老师们想要的事情......你花了很多时间去找出如何不做。这对于一个程序员来说是非常有价值的。 - K Scott Piel
另外,为什么我发布的第二段代码无法编译? - Bodosko
可能是Convert integer to string without access to libraries的重复内容。这是SO上itoa的第四个命中结果。很惊讶你错过了它。 - Raymond Chen
显示剩余2条评论
6个回答

11
当然不可能,因为数组是一个对象并需要存储。强制转换产生的是值而不是对象。有人会说C语言的整个重点/优势在于您对对象的存储和生命周期拥有控制。
生成包含整数十进制表示的字符串的正确方法是自己创建存储并使用snprintf函数。
char buf[sizeof(int)*3+2];
snprintf(buf, sizeof buf, "%d", n);

5
你需要将500转换为"500""500"'5''0''0'0相同。最后一个元素0是字符串的空终止符。 500等于5 * 100 + 0 * 10 + 0 * 1。你需要进行一些数学计算。基本上,你需要使用/运算符。
此外,'5''0' + 5相同,这可能也有用。

1
但这样我就不会使用强制转换。我可以想象出许多实现我所需的方法,但它们中的任何一个都涉及到强制转换,而我甚至不知道是否可能。 - Bodosko
1
要求您使用强制转换并不实际。这就像告诉某人必须使用计算器来解决他们已经在脑中解决的问题一样。只需无需强制转换进行解决。(如果必须,可以插入一个虚拟转换,就像在计算器中输入1+1=一样。) - Raymond Chen

2
由于字节顺序问题,强制类型转换并不是一个好的方式来解决这个问题。但是这里还是给出一个例子,有时它仍然有用(尽管由于编译器对这些类型的强制转换的处理方式,联合体现在更好地工作)。
#include <stdio.h> //for printf 
#define INT(x) ((int*)(x)) //these are not endian-safe methods
#define CHAR(x) ((char*)(x))
int main(void)
{
    int *x=INT(&"HI !");
    printf("%X\n",*x); //look up the ascii and note the order
    printf("%s\n",CHAR(x));
    return 0;
}

对于一个值小于500的int类型,如果最高位字节在前,你会得到一个指向""(或{0})的"字符串"(指向char数组的指针),但如果字节顺序是LSB先(x86为小端序),那么你将得到一个可用的3字节的"字符串" char*(不一定是人类可读的字符),但不能保证在整数中会有零字节,并且由于你只有指向存储int的地址的指针,如果你在其上运行正常的字符串函数,则它们会越过原始int的末尾进入无主之地(在小型测试程序中,通常是环境变量)...无论如何,为了更好的可移植性,可以使用网络字节序(对于小端序来说是一个无操作):

#include <arpa/inet.h>
uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);

这些函数会根据需要进行字节交换,以获得网络字节顺序。在您的x86上,它们将被优化掉,因此为了可移植性,最好使用它们。


2

不直接给出代码,你需要做的是循环遍历整数的每个数字(通过使用%运算符计算其余数模10),然后将其值添加到'0'的ASCII值上,将结果强制转换为char类型,并将该结果放入以null结尾的字符串中。

一个假装隐式转换不存在的例子可能如下所示:

char c = (char) ( ((int) '0') + 5 ); // c should now be '5'.

您可以通过计算数字的以10为底的对数来确定结果字符串的长度,或者通过使用realloc()动态分配字符串长度。


1

仅仅因为它还没有被列出来:这里有一种方法可以使用snprintf将int转换为可变大小分配的char数组:

int value = 5

// this will just output the length which is to expect
int length = snprintf( NULL, 0, "%d", value );

char* valueAsString = malloc( length + 1 );// one more for 0-terminator
snprintf( valueAsString, length + 1, "%d", value );

0

获取分区数量,然后逐个添加到您的缓冲区中

char *int2str(int nb) {
    int i = 0;
    int div = 1;
    int cmp = nb;
    char *nbr = malloc(sizeof(char) * 12);

    if (!nbr)
        return (NULL);
    if (nb < 0)
        nbr[i++] = '-';
    while ((cmp /= 10) != 0)
        div = div * 10;
    while (div > 0) {
        nbr[i++] = abs(nb / div) + 48;
        nb = nb % div;
        div /= 10;
    }
    nbr[i] = '\0';
    return (nbr);
}

更加紧凑:
char *lotaa(long long nb) {
    int size = (nb ? floor(log10(llabs(nb))) : 0) + (nb >= 0 ? 1 : 2);
    char *str = malloc(size + 1);

    str[0] = '-';
    str[size] = 0;
    for(nb = llabs(nb); nb > 0 || (size > 0 && str[1] == 0); nb /= 10)
        str[--size] = '0' + nb % 10;
    return (str);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接