简体   繁体   English

在 C 中将 int 转换为 char 数组

[英]Cast int to char array in C

Is is possible to convert int to "string" in C just using casting?是否可以仅使用强制转换在 C 中将 int 转换为“字符串”? Without any functions like atoi() or sprintf() ?没有像atoi()sprintf()这样的函数吗?

What I want would be like this:我想要的是这样的:

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

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

The reason is that I need to generate two random ints (0 to 500) and send both as one string in a message queue to another process.原因是我需要生成两个随机整数(0 到 500)并将它们作为消息队列中的一个字符串发送到另一个进程。 The other process receives the message and do the LCM.另一个进程接收消息并执行 LCM。

I know how to do with atoi() and itoa() .我知道如何处理atoi()itoa() But my teachers wants just using cast.但是我的老师只想使用演员表。

Also, why isn't the following possible to compile?另外,为什么不能编译以下内容?

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;
}

Of course it's not possible, because an array is an object and needs storage .当然这是不可能的,因为数组是一个对象并且需要storage Casts result in values , not objects .转换结果是,而不是对象 Some would say the whole point/power of C is that you have control over the storage and lifetime of objects.有人会说 C 的全部意义/力量在于您可以控制对象的存储和生命周期。

The proper way to generate a string containing a decimal representation of an integer is to create storage for it yourself and use snprintf :生成包含整数的十进制表示的字符串的正确方法是自己为它创建存储并使用snprintf

char buf[sizeof(int)*3+2];
snprintf(buf, sizeof buf, "%d", n);

You have to convert 500 to "500" .您必须将500转换为"500"

"500" is the same as '5' then '0' then '0' then 0 . "500"'5' then '0' then '0' then 0 The last element 0 is the null terminator of a string.最后一个元素0是字符串的空终止符。

500 is equal to 5 * 100 + 0 * 10 + 0 * 1 . 500等于5 * 100 + 0 * 10 + 0 * 1 You have to do some math here.你必须在这里做一些数学运算。 Basically you have to use the / operator.基本上你必须使用/操作符。

Then this could be also useful: '5' is the same as '0' + 5 .那么这也可能有用: '5''0' + 5

Without giving away an exact coded answer, what you'll want to do is loop through each digit of the integer (by computing its remainder modulo 10 via the % operator), and then add its value to the ASCII value of '0', casting the result back to a char, and placing that result in a null-terminated string.在不给出确切编码答案的情况下,您要做的是遍历整数的每个数字(通过 % 运算符计算其余数模 10),然后将其值添加到 ASCII 值“0”,将结果转换回字符,并将结果放入以空字符结尾的字符串中。

An example which pretends like implicit casts don't exist might look like this:一个假装不存在隐式强制转换的示例可能如下所示:

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

You can determine the length of the resulting string by computing the log base 10 of the number, or by simply allocating it dynamically as you go using realloc().您可以通过计算数字的对数以 10 为底来确定结果字符串的长度,或者在使用 realloc() 时简单地动态分配它。

Casting is a horrible way to do this due to endianness, but here is an example anyhow - there are some occasions where it is useful (unions work better these days though, due to compiler handling of these types of casts).由于字节顺序,强制转换是一种可怕的方法,但无论如何这里有一个例子 - 在某些情况下它很有用(不过,由于编译器处理这些类型的强制转换,现在联合工作得更好)。

#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;
}

For an int with a value <500, if the most significant byte comes first, then you get a "string" (pointer to a char array) of "" (or {0}) but if the endianness is LSB first (x86 is little endian) then you would get a usable 3 byte "string" char* (not necessarily human readable characters) but there is no guarantee that there will be a zero byte in an integer and since all you have is a pointer to the address where the int was stored, if you were to run normal string functions on it, they would go past the end of the original int into no-mans-land (in small test programs it will often be environment variables) ... anyhow for more portability you can use network byte order (which for little endian is a no-op):对于值 <500 的 int,如果最重要的字节在前,那么您会得到一个“字符串” (指向字符数组的指针)“”(或 {0})但如果字节序是 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);

These functions just byteswap as necessary to get network byte order.这些函数只是根据需要进行字节交换以获得网络字节顺序。 On your x86 they will be optimized away, so you might as well use them for portability.在您的 x86 上,它们将被优化掉,因此您不妨将它们用于便携性。

Just because it is not listed yet: Here a way to convert int to char array with variable size allocation by using snprintf :仅仅因为它还没有列出:这是一种使用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 );

get the number of divisions then add one by one to your buffer获取分区数然后一一添加到您的缓冲区中

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);
}

Even more compact:更紧凑:

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);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM