无符号字符在字节操作上溢出

huangapple go评论65阅读模式
英文:

Unsigned char overflow on byte operations

问题

我正在尝试创建一个函数,它可以将任何类型(float、int、double等)的两个数字相加,并将结果保存到另一个相同类型的数字中。

我研究了void *,并了解到通过将其强制转换为unsigned char *,我可以获得每个数字的每个字节。

我面临的问题是,当我添加的数字大于unsigned char的范围时,它会发生包装。所以在我的情况下,255 + 1 = 0

这是我目前的代码,

typedef unsigned char byte;

// add two numbers (of any type) of size abc_size and save in c
void add(void *a, void *b, void *c, size_t abc_size) {
    byte *a_bytes = (byte *) a;
    byte *b_bytes = (byte *) b;
    byte *c_bytes = (byte *) c;

    for (size_t i = 0; i < abc_size; i++) {
        byte a_byte = a_bytes[i];
        byte b_byte = b_bytes[i];

        byte sum = a_byte + b_byte; // do i have to account for carry or endianess?
        c_bytes[i] = sum;
    }
}

以及我用于测试的主要函数,

#include <stdio.h>

int main(void) {
    int a = 255;
    int b = 1;
    int c = 0;

    add(&a, &b, &c, sizeof(int));

    printf("%d + %d = %d\n", a, b, c);
}

上面的输出是,

255 + 1 = 0

当我尝试添加floatsdoubles时,我也面临问题,结果完全出乎意料,并且我想这可能又是因为溢出。

这种方法对于任何数字和任何类型都能工作吗?如果可以,我需要做哪些改变?

提前感谢您的帮助。

英文:

I am trying to make a function that adds two numbers of any type (float, int, double etc), and saves the result into another number of the same type.

I was looking into void * and learned that by casting to unsigned char *, I can get each byte of each number.

The problem I am facing is, that when I add something greater than the range of an unsigned char, it wraps around. So in my case 255 + 1 = 0.

This my code so far,

typedef unsigned char byte;

// add two numbers (of any type) of size abc_size and save in c
void add(void *a, void *b, void *c, size_t abc_size) {
    byte *a_bytes = (byte *) a;
    byte *b_bytes = (byte *) b;
    byte *c_bytes = (byte *) c;

    for (size_t i = 0; i &lt; abc_size; i++) {
        byte a_byte = a_bytes[i];
        byte b_byte = b_bytes[i];

        byte sum = a_byte + b_byte; // do i have to account for carry or endianess?
        c_bytes[i] = sum;
    }
}

and the main I used for testing,

#include &lt;stdio.h&gt;

int main(void) {
    int a = 255;
    int b = 1;
    int c = 0;

    add(&amp;a, &amp;b, &amp;c, sizeof(int));

    printf(&quot;%d + %d = %d\n&quot;, a, b, c);
}

The output of the above is,

255 + 1 = 0

I am also facing a problem when I am trying to add floats or doubles, which the result is completely unexpected, and I would image is again because of the overflow.

Can this method work at all for any number and any type? If so, what do I need to change?

Thank you in advance.

答案1

得分: 4

你正在试图重复造轮子,而你的简单方法将无法处理任何浮点数。使用通用选择。

#define add(a,b) _Generic((a), \
            double: addd, \
            default: addu,  \
            float:  addf,  \
            int: addi \
            )(a,b)
            
double addd(double a, double b)
{
    return a+b;
}

float addf(float a, float b)
{
    return a+b;
}

unsigned addu(unsigned a, unsigned b)
{
    return a+b;
}

int addi(int a, int b)
{
    return a+b;
}

int main(void)
{
    printf("%u %i %f\n", add(1u, 4u), add(-3,1), add(3.0, 1.5));
}

你可以在这个链接中查看代码:https://godbolt.org/z/T3nsdvKn1

英文:

You are trying to reinvent the wheel and your naive method will not work with any floating point numbers. use generic selection

#define add(a,b) _Generic((a), \
            double: addd, \
            default: addu,  \
            float:  addf,  \
            int: addi \
            )(a,b)


double addd(double a, double b)
{
    return a+b;
}

float addf(float a, float b)
{
    return a+b;
}

unsigned addu(unsigned a, unsigned b)
{
    return a+b;
}

int addi(int a, int b)
{
    return a+b;
}

int main(void)
{
    printf(&quot;%u %i %f\n&quot;, add(1u, 4u), add(-3,1), add(3.0, 1.5));
}

https://godbolt.org/z/T3nsdvKn1

huangapple
  • 本文由 发表于 2023年5月28日 07:15:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/76349387.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定