C 在不使用第三个变量的情况下交换字符

C 在不使用第三个变量的情况下交换字符,c,C,C中的字符实际上是一些ascii数字。那么,为什么下面的代码(应该交换两个字符)会给出错误的结果呢 void swap(char *a,char *b) { *a=*a+*b; *b=*a-*b; *a=*a-*b; } 理论上,这个计算看起来不错。让我们通过示例来了解它: 让我们看一下a='s'=83和b='O'=79 a = a + b = 83 + 79 = 162 如果您的编译器将char定义为无符号,那么溢出就没有问题。如果编译器定义了要签名的char,则这

C中的字符实际上是一些ascii数字。那么,为什么下面的代码(应该交换两个字符)会给出错误的结果呢

void swap(char *a,char *b)
{
    *a=*a+*b;
    *b=*a-*b;
    *a=*a-*b;
}

理论上,这个计算看起来不错。让我们通过示例来了解它:

让我们看一下
a='s'=83
b='O'=79

a = a + b = 83 + 79 = 162
如果您的编译器将
char
定义为无符号,那么溢出就没有问题。如果编译器定义了要签名的
char
,则这超出范围(>127),并导致
a=-94

b = a - b = (-94) - 79 = -173
再次超出范围,收益率为83,这是正常的

a = a - b = (-94) - (-173) - = 79
这看起来也不错

实际上,这段代码对我来说毫无问题:

char a = 'S', b = 'O';
swap(&a, &b);
assert(a == 'O');
assert(b == 'S');
使用您提供的确切的
swap
功能


下面是。

如果上面的表达式会导致算术溢出,那么结果会很奇怪。如果
a
b
两个指针都指向同一位置*,上述方法也将失败

试试这个:

void swap(char *a,char *b)
{
    if (a == b) // Check if the two addresses are same
      return;

    *a=*a^*b;
    *b=*a^*b;
    *a=*a^*b;
}  

*如果
a
b
将指向同一位置,比如
x100
,并让存储在该位置的值为
0111
(二进制),则:

两个问题

  • 最后一行
    *a=*a-*b
    实际上可以归结为
    *a=*a-*a

  • char
    可以是
    signed
    unsigned
    。这是编译器所做的选择;C标准允许这两种情况。因此,
    *a-*b
    的值可能因平台而异


  • 可以在没有临时协议的情况下进行交换。这项技术(异或交换)已经有很好的文档记录,但由于一些恶劣的边缘情况,不建议使用它。

    如果指针相等,这将不起作用。所以这需要首先检查和处理

    为了解决机器上的问题,您应该编写如下测试,并使用其他printf输出分析结果,例如:

    void swap(char *a, char *b)
    {
        /* if (a != b){ */
        *a = *a + *b;
        *b = *a - *b;
        *a = *a - *b;
        /*}*/
    }
    
    void swapTemp(char *a, char *b)
    {
        char temp = *a;
        *a = *b;
        *b = temp;
    }
    
    int
    main(){
        unsigned int errors = 0;
        int b;
        for (b = 0; b <= 255; b++)
        {
            int a;
            for (a = 0; a <= 255; a++)
            {
                char a_swap = a;
                char a_swapTemp = a;
                char b_swap = b;
                char b_swapTemp = b;
                swap(&a_swap, &b_swap);
                swapTemp(&a_swapTemp, &b_swapTemp);
                if ((a_swap != a_swapTemp) || (b_swap != b_swapTemp))
                    ++errors;
                /* extend to print results here to analyse the problem */
            }
        }
        printf("There where %u errors!", errors);
        return 0;
    }
    
    void交换(char*a,char*b)
    {
    /*如果(a!=b){*/
    *a=*a+*b;
    *b=*a-*b;
    *a=*a-*b;
    /*}*/
    }
    无效交换(字符*a,字符*b)
    {
    字符温度=*a;
    *a=*b;
    *b=温度;
    }
    int
    main(){
    无符号整数错误=0;
    int b;
    
    对于(b=0;b您的输入是什么?您得到了什么结果?我发送两个字符的地址,比如swap(&ch1,&ch2)。您也可以使用预处理器:
    #define swap(a,b)do{a^=b;b^=a;a^=b;}while(0)
    @codemonkey,如果a和b相等,它将严重失败。用一个简短的程序显示它失败了如何?我怀疑
    ch1
    ch2
    在您的
    交换(&ch1,&ch2)中
    实际上并不是
    char
    ——可能是
    char*
    ?或者
    int
    ?还有,什么平台?比较地址是不够的。不同位置的相等值仍然会导致0。@Daerst:我正在考虑把我迄今为止的职业收入赌在你这里是不正确的;-)甚至我也尝试用异或交换字符,但没有成功work@user3437973;您的输入是什么?我正在发送两个字符的地址,比如说swap(&ch1,&ch2),上次他设置
    *a
    实际上是
    a=a-b=(a+b)-a=b
    ,而不是
    a=a-b=a-a=0
    …因为他当时已经设置了
    *a=*a+*b;
    。他的问题是另外一个问题。#include int main(){int a,b;printf(“输入两个要交换的整数”);scanf(%d%d),&a,&b);a=a+b;b=a-b;printf(“a=%d\n”,a,b);返回0;}此操作有效fine@Daerst您给出的原因实际上是“为什么我不能在同一地址交换值”的原因也就是说,如果a=b,那么为什么我不能自己交换一个数字。我更改了答案并删除了我原来错误的数学解释。代码对我来说很好。@user3437973,请提供失败的实际输入。@Daerst即使对于a='a'和b='b',它也失败了!
    void swap(char *a, char *b)
    {
        /* if (a != b){ */
        *a = *a + *b;
        *b = *a - *b;
        *a = *a - *b;
        /*}*/
    }
    
    void swapTemp(char *a, char *b)
    {
        char temp = *a;
        *a = *b;
        *b = temp;
    }
    
    int
    main(){
        unsigned int errors = 0;
        int b;
        for (b = 0; b <= 255; b++)
        {
            int a;
            for (a = 0; a <= 255; a++)
            {
                char a_swap = a;
                char a_swapTemp = a;
                char b_swap = b;
                char b_swapTemp = b;
                swap(&a_swap, &b_swap);
                swapTemp(&a_swapTemp, &b_swapTemp);
                if ((a_swap != a_swapTemp) || (b_swap != b_swapTemp))
                    ++errors;
                /* extend to print results here to analyse the problem */
            }
        }
        printf("There where %u errors!", errors);
        return 0;
    }