Intercambiar dos valores variables sin usar la tercera variable

104

Una de las preguntas más difíciles que se hacen en una entrevista.

Intercambia los valores de dos variables como a=10y b=15.

Generalmente, para intercambiar dos valores de variables, necesitamos una tercera variable como:

temp=a;
a=b;
b=temp;

Ahora el requisito es intercambiar valores de dos variables sin usar la tercera variable.

Muhammad Akhtar
fuente
76
Guau. En mi humilde opinión, una pregunta de entrevista mal elegida. Esta es una técnica que rara vez, si es que alguna vez, es útil en la práctica. Existe una buena posibilidad de que solo confunda el optimizador del compilador y dé como resultado un código menos eficiente que un "intercambio temporal". A menos que este lugar en el que estaba entrevistando se involucre en asuntos muy matemáticos (piense: desarrollo de algoritmos de cifrado o similares), no puedo imaginar una buena razón para hacer esa pregunta.
Dan Moulding
10
De hecho, esa pregunta no le dice nada más que si el candidato conoce este truco en particular que es bastante inútil en el código de producción. Supongo que es posible que te encuentres con algún mago ocasional que lo adivine sobre la marcha, pero es probable que las personas así que no conocen el truco sean bastante raras.
ceo
2
¿Quizás quieran eliminar a las personas que piensan que conocer esos trucos es lo que hace a un buen programador? Además, cuando lea sobre el xor-trick, preste atención a cuándo fallará (lo que, en mi opinión, lo hace prácticamente inútil para el intercambio de enteros de propósito general).
UncleBens

Respuestas:

155

Usando el algoritmo de intercambio xor

void xorSwap (int* x, int* y) {
    if (x != y) { //ensure that memory locations are different
       *x ^= *y;
       *y ^= *x;
       *x ^= *y;
    }
}


¿Por qué la prueba?

La prueba es para asegurar que xey tengan diferentes ubicaciones de memoria (en lugar de valores diferentes). Esto se debe a que, (p xor p) = 0y si tanto x como y comparten la misma ubicación de memoria, cuando uno se establece en 0, ambos se establecen en 0. Cuando tanto * x como * y son 0, todas las demás operaciones xor en * x e * y serán iguales 0 (ya que son iguales), lo que significa que la función establecerá tanto * x como * y en 0.

Si tienen los mismos valores pero no la misma ubicación de memoria, todo funciona como se esperaba

*x = 0011
*y = 0011
//Note, x and y do not share an address. x != y

*x = *x xor *y  //*x = 0011 xor 0011
//So *x is 0000

*y = *x xor *y  //*y = 0000 xor 0011
//So *y is 0011

*x = *x xor *y  //*x = 0000 xor 0011
//So *x is 0011


¿Debería usarse esto?

En casos generales, no. El compilador optimizará la variable temporal y dado que el intercambio es un procedimiento común, debería generar el código de máquina óptimo para su plataforma.

Tomemos, por ejemplo, este programa de prueba rápida escrito en C.

#include <stdlib.h>
#include <math.h>

#define USE_XOR 

void xorSwap(int* x, int *y){
    if ( x != y ){
        *x ^= *y;
        *y ^= *x;
        *x ^= *y;
    }
}

void tempSwap(int* x, int* y){
    int t;
    t = *y;
    *y = *x;
    *x = t;
}


int main(int argc, char* argv[]){
    int x = 4;
    int y = 5;
    int z = pow(2,28); 
    while ( z-- ){
#       ifdef USE_XOR
            xorSwap(&x,&y);
#       else
            tempSwap(&x, &y);
#       endif
    }
    return x + y;    
}

Compilado usando:

gcc -Os main.c -o swap

La versión xor lleva

real    0m2.068s
user    0m2.048s
sys  0m0.000s

Donde como toma la versión con la variable temporal:

real    0m0.543s
user    0m0.540s
sys  0m0.000s
Yacoby
fuente
1
Podría valer la pena explicar el por qué de la prueba (es decir, que el enfoque triple xor falla terriblemente si xey hacen referencia al mismo objeto).
dmckee --- ex-moderador gatito
1
No sé cómo consiguió tantos votos positivos cuando el código está tan roto. Ambos intercambios en el segmento de código probado son completamente incorrectos. Mira de cerca.
SoapBox
@SoapBox: ¡Muy buen punto! El XOR intercambia ceros x & deja y sin tocar, y el intercambio temporal deja ambos con el valor de x. ¡Ups!
Drew Hall
4
@SoapBox Buena captura. Arreglado y probado nuevamente y no obtengo ninguna diferencia importante en los tiempos.
Yacoby
4
El interrogador dijo dos variables, no enteras. : P
Plumenator
93

la forma general es:

A = A operation B
B = A inverse-operation B
A = A inverse-operation B 

sin embargo, es posible que tenga cuidado con los desbordamientos y tampoco todas las operaciones tienen una inversa que esté bien definida para todos los valores que la operación está definida. p. ej. * y / trabajar hasta que A o B sea 0

xor es particularmente agradable ya que se define para todos los ints y es su propio inverso

jk.
fuente
XOR (X, X) == 0, entonces xor funciona para ints EXCEPTO cuando los dos valores que se intercambian son iguales. No soy el primero en señalar esto y muchos lo han dicho (aquí y en otros lugares) para señalar a alguien como un crédito.
AlanK
85
a = a + b
b = a - b // b = a
a = a - b
Insecto
fuente
16
¿Y si se a+bdesborda?
Alok Singhal
2
@Alok: Eso no se tiene en cuenta, por lo que no es práctico :)
Dor
4
Si A y B son de la misma, los tipos enteros básicos, tamaño (como int, unsigned short, ...), que todavía funciona en el final, incluso con desbordamiento, ya que si a + b desborda, entonces a - b se subdesbordamiento. Con estos tipos de enteros básicos, los valores simplemente se mueven.
Patrick Johnmeyer
10
En C, usar esto en unsignedtipos enteros está bien y siempre funciona. En tipos firmados, invocaría un comportamiento indefinido en caso de desbordamiento.
jpalecek
1
@Shahbaz: Incluso si los enteros con signo se almacenan en complemento a 2, el comportamiento en el desbordamiento aún no está definido.
Keith Thompson
79

Nadie ha sugerido usarlo std::swaptodavía.

std::swap(a, b);

No utilizo ninguna variable temporal y dependiendo del tipo ay bla implementación puede tener una especialización que tampoco. La implementación debe escribirse sabiendo si un 'truco' es apropiado o no. No tiene sentido intentar adivinar.

De manera más general, probablemente querría hacer algo como esto, ya que funcionaría para tipos de clases que permitan a ADL encontrar una mejor sobrecarga si es posible.

using std::swap;
swap(a, b);

Por supuesto, la reacción del entrevistador a esta respuesta podría decir mucho sobre la vacante.

CB Bailey
fuente
por supuesto, en C ++ 0x swap usará referencias rvalue, ¡así que será aún mejor!
jk.
16
Todo el mundo quiere mostrar el brillante xor u otro truco que aprendieron, con varias advertencias sobre cómo usarlo, pero esta es sin duda la mejor respuesta.
2
por qué no std :: swap (a, b); ? Quiero decir, ¿por qué el uso?
Dinaiz
2
@Dinaiz sin el std::, las swapimplementaciones definidas por el usuario para los tipos definidos por el usuario también están disponibles para llamar (esto es lo que se entiende por "funcionaría para los tipos de clase que permitan a ADL encontrar una mejor sobrecarga si es posible").
Kyle Strand
std::swaputiliza memoria temporal adicional en su implementación ¿no? cplusplus.com/reference/utility/swap
Ninja
19

Como ya señaló manu, el algoritmo XOR es uno de los populares que funciona para todos los valores enteros (que incluye punteros, con algo de suerte y conversión). En aras de la integridad, me gustaría mencionar otro algoritmo menos poderoso con suma / resta:

A = A + B
B = A - B
A = A - B

Aquí debe tener cuidado con los desbordamientos / subdesbordamientos, pero de lo contrario, funciona igual de bien. Incluso puede probar esto en flotadores / dobles en el caso de que XOR no esté permitido en ellos.

Vilx-
fuente
" todos los valores enteros (que incluyen punteros entonces) " - ¿Qué? No, los punteros no son números enteros y no puede modificar los valores de puntero. Tampoco puede xor valores de punto flotante. Pero el método de suma / resta tiene un comportamiento indefinido (para tipos con signo o de punto flotante) en desbordamiento o subdesbordamiento, puede perder precisión para el punto flotante y no se puede aplicar a punteros u otros tipos no numéricos.
Keith Thompson
@KeithThompson: OK, la pérdida de precisión para los puntos flotantes es cierta, pero dependiendo de las circunstancias, podría ser aceptable. En cuanto a los punteros, bueno, nunca he oído hablar de un compilador / plataforma en el que los punteros no se puedan lanzar libremente a números enteros y viceversa (teniendo cuidado de elegir un número entero del tamaño correcto, por supuesto). Pero claro, no soy un experto en C / C ++. Sé que va en contra del estándar, pero tenía la impresión de que este comportamiento es bastante consistente en ... todo.
Vilx-
1
@ Vilx-: ¿Por qué sería aceptable la pérdida de precisión cuando es tan fácil evitarla usando una variable temporal std::swap()? Claro, puede convertir punteros en números enteros y viceversa (asumiendo que hay un tipo de entero lo suficientemente grande, lo cual no está garantizado), pero eso no es lo que sugirió; insinuó que los punteros son números enteros, no que se puedan convertir en números enteros. Sí, la respuesta aceptada no funcionará para los punteros. La respuesta de Charles Bailey utilizando std::swapes realmente la única correcta.
Keith Thompson
1
En primer lugar, la pregunta era "cómo intercambiar sin utilizar una tercera variable" y la razón dada para ello fue "una pregunta de entrevista". Solo di otra posible respuesta. En segundo lugar, está bien, mis disculpas por insinuar que los punteros son números enteros. Actualicé la respuesta para que sea más explícita y correcta. Corrígeme si sigo equivocado (o actualiza la respuesta tú mismo). En tercer lugar, eliminé la parte sobre la respuesta aceptada. No está utilizando conversiones de puntero a entero en ningún lugar y funciona correctamente (hasta donde tengo entendido).
Vilx-
@KeithThompson: La pregunta podría modificarse para saber cómo std::swapse puede implementar sin usar una tercera variable.
jxh
10

Las preguntas estúpidas merecen respuestas adecuadas:

void sw2ap(int& a, int& b) {
  register int temp = a; // !
  a = b;
  b = temp;
}

El único buen uso de la registerpalabra clave.

MSalters
fuente
1
¿Un objeto declarado con registro de clase de almacenamiento no es una "variable"? Además, no estoy convencido de que este sea un buen uso de register, ya que si su compilador no puede optimizar esto ya, ¿cuál es el punto de intentarlo? Debería aceptar cualquier basura que obtenga o escribir el ensamblaje usted mismo ;-) Pero como usted dice, una pregunta dudosa merece una respuesta dudosa.
Steve Jessop
1
Casi todos los compiladores modernos ignoran la clase de almacenamiento de registros, ya que tienen una idea mucho mejor de lo que se accede con frecuencia que usted.
ceo
6
Tenga en cuenta que esta respuesta está destinada a entrevistadores, no a compiladores. Se aprovecha especialmente del hecho de que el tipo de entrevistadores que hacen este tipo de preguntas no entienden realmente C ++. Entonces, no pueden rechazar esta respuesta. (y no hay una respuesta estándar; ISO C ++ habla de objetos, no de variables).
MSalters
Ah, te entiendo. Estaba buscando en el estándar C la mención de variable como sustantivo, y no solo significando no constante. Encontré uno en n1124, en la sección de bucles for que definen el alcance de las "variables" declaradas en el inicializador. Luego me di cuenta de que la pregunta era C ++, y no me molesté en buscar para ver si C ++ había cometido el mismo error tipográfico en alguna parte.
Steve Jessop
3

Intercambiar dos números usando la tercera variable sería así,

int temp;
int a=10;
int b=20;
temp = a;
a = b;
b = temp;
printf ("Value of a", %a);
printf ("Value of b", %b);

Intercambiar dos números sin usar la tercera variable

int a = 10;
int b = 20;
a = a+b;
b = a-b;
a = a-b;
printf ("value of a=", %a);
printf ("value of b=", %b);
Ashwini
fuente
2
#include<iostream.h>
#include<conio.h>
void main()
{
int a,b;
clrscr();
cout<<"\n==========Vikas==========";
cout<<"\n\nEnter the two no=:";
cin>>a>>b;
cout<<"\na"<<a<<"\nb"<<b;
a=a+b;
b=a-b;
a=a-b;

cout<<"\n\na="<<a<<"\nb="<<b;
getch();
}
vikas
fuente
1
Después de cout << "Enter the two no=:"que esperaba leercout << "Now enter the two no in reverse order:"
user253751
Al igual que con otras respuestas, esto tiene un comportamiento indefinido si a+bo a-bdesbordamientos. Además, void main()no es válido y <conio.h>no es estándar.
Keith Thompson
2

Dado que la solución original es:

temp = x; y = x; x = temp;

Puede convertirlo en un delineador de dos usando:

temp = x; y = y + temp -(x=y);

Luego conviértalo en un delineador usando:

x = x + y -(y=x);
user3258202
fuente
1
Comportamiento indefinido. yse lee y escribe en la misma expresión sin ningún punto de secuencia intermedio.
Keith Thompson
1

Si cambia un poco la pregunta para preguntar sobre 2 registros de ensamblaje en lugar de variables, puede usar también la xchgoperación como una opción y la operación de pila como otra.

rkellerm
fuente
1
¿A qué xchgoperación te refieres? La pregunta no especificó una arquitectura de CPU.
Keith Thompson
1

Considere a=10, b=15:

Usando la suma y la resta

a = a + b //a=25
b = a - b //b=10
a = a - b //a=15

Usando división y multiplicación

a = a * b //a=150
b = a / b //b=10
a = a / b //a=15
Venkat
fuente
1
Tiene un comportamiento indefinido en caso de desbordamiento.
Keith Thompson
1
Además, en C ++, puede tener un comportamiento no deseado cuando los valores no son del mismo tipo. Por ejemplo, a=10y b=1.5.
Matthew Cole
1
#include <iostream>
using namespace std;
int main(void)
{   
 int a,b;
 cout<<"Enter a integer" <<endl;
 cin>>a;
 cout<<"\n Enter b integer"<<endl;
 cin>>b;

  a = a^b;
  b = a^b;
  a = a^b;

  cout<<" a= "<<a <<"   b="<<b<<endl;
  return 0;
}

Actualización: en esto estamos tomando la entrada de dos enteros del usuario. Entonces usamos la operación XOR bit a bit para intercambiarlos.

Digamos que tenemos dos enteros a=4y b=9ya continuación:

a=a^b --> 13=4^9 
b=a^b --> 4=13^9 
a=a^b --> 9=13^9
Naeem Ul Hassan
fuente
Agregue una breve explicación a su respuesta para futuros visitantes.
Nikolay Mihaylov
1
En esto, estamos tomando la entrada de dos números enteros del usuario. Entonces estamos usando la operación xor bit a bit o dos los intercambian. Digamos que tenemos dos números enteros a = 4 y b = 9, entonces ahora a = a ^ b -> 13 = 4 ^ 9 b = a ^ b -> 4 = 13 ^ 9 a = a ^ b -> 9 = 13 ^ 9
Naeem Ul Hassan
1

Aquí hay una solución más pero con un solo riesgo.

código:

#include <iostream>
#include <conio.h>
void main()
{

int a =10 , b =45;
*(&a+1 ) = a;
a =b;
b =*(&a +1);
}

cualquier valor en la ubicación a + 1 será anulado.

Temerario
fuente
2
Fue una respuesta útil, quizás el valor desapareció.
Bibi Tahira
1
Varios tipos de comportamiento indefinido. *(&a+1)bien podría ser b. void main()no es válido. <conio.h>no es estándar (y ni siquiera lo usa).
Keith Thompson
El código fue probado con otros parámetros de salida, que excluyeron, como ya he mencionado, un riesgo. El riesgo de anular la memoria ... Eso está ahí ... Pero fue útil intercambiar dos variables sin la participación de la tercera.
DareDevil
La peor parte es que en realidad puede funcionar algunas veces, por lo que es posible que no se dé cuenta de inmediato de que está completamente roto y fallará con la optimización, otros compiladores, etc.
avl_sweden
1

Por supuesto, la respuesta de C ++ debería ser std::swap.

Sin embargo, tampoco existe una tercera variable en la siguiente implementación de swap:

template <typename T>
void swap (T &a, T &b) {
    std::pair<T &, T &>(a, b) = std::make_pair(b, a);
}

O, como una sola línea:

std::make_pair(std::ref(a), std::ref(b)) = std::make_pair(b, a);
jxh
fuente
0
#include <stdio.h>

int main()
{
    int a, b;
    printf("Enter A :");
    scanf("%d",&a);
    printf("Enter B :");
    scanf("%d",&b);
    a ^= b;
    b ^= a;
    a ^= b;
    printf("\nValue of A=%d B=%d ",a,b);
    return 1;
}
Siddiqui
fuente
0

ese es el algoritmo de intercambio XOR correcto

void xorSwap (int* x, int* y) {
   if (x != y) { //ensure that memory locations are different
      if (*x != *y) { //ensure that values are different
         *x ^= *y;
         *y ^= *x;
         *x ^= *y;
      }
   }
}

debe asegurarse de que las ubicaciones de la memoria sean diferentes y también de que los valores reales sean diferentes porque A XOR A = 0

Gianluca Ghettini
fuente
No tiene que asegurarse de que los valores sean diferentes.
user253751
0

Puede hacerlo ... de manera fácil ... dentro de una línea Logic

#include <stdio.h>

int main()
{
    int a, b;
    printf("Enter A :");
    scanf("%d",&a);
    printf("Enter B :");
    scanf("%d",&b);
    int a = 1,b = 2;
    a=a^b^(b=a);
    printf("\nValue of A=%d B=%d ",a,b);

    return 1;
}

o

#include <stdio.h>

int main()
{
    int a, b;
    printf("Enter A :");
    scanf("%d",&a);
    printf("Enter B :");
    scanf("%d",&b);
    int a = 1,b = 2;
    a=a+b-(b=a);
    printf("\nValue of A=%d B=%d ",a,b);

    return 1;
}
MOHAMMAD S HUSSAIN
fuente
1
Comportamiento indefinido. En ambas versiones, bse lee y modifica dentro de la misma expresión, sin un punto de secuencia intermedio.
Keith Thompson
0
public void swapnumber(int a,int b){
    a = a+b-(b=a);
    System.out.println("a = "+a +" b= "+b);
}
Ashish Bhavsar
fuente
0

La mejor respuesta sería usar XOR y usarlo en una línea sería genial.

    (x ^= y), (y ^= x), (x ^= y);

x, y son variables y la coma entre ellas introduce los puntos de secuencia para que no dependa del compilador. ¡Salud!

Ankit Sharma
fuente
0

Veamos un ejemplo simple de c para intercambiar dos números sin usar la tercera variable.

programa 1:

#include<stdio.h>
#include<conio.h>
main()
{
int a=10, b=20;
clrscr();
printf("Before swap a=%d b=%d",a,b);
a=a+b;//a=30 (10+20)
b=a-b;//b=10 (30-20)
a=a-b;//a=20 (30-10)
printf("\nAfter swap a=%d b=%d",a,b);
getch();
}

Salida:

Antes del intercambio a = 10 b = 20 Después del intercambio a = 20 b = 10

Programa 2: Uso de * y /

Veamos otro ejemplo para intercambiar dos números usando * y /.

#include<stdio.h>
#include<conio.h>
main()
{
int a=10, b=20;
clrscr();
printf("Before swap a=%d b=%d",a,b);
a=a*b;//a=200 (10*20)
b=a/b;//b=10 (200/20)
a=a/b;//a=20 (200/10)
printf("\nAfter swap a=%d b=%d",a,b);
getch();
}

Salida:

Antes del intercambio a = 10 b = 20 Después del intercambio a = 20 b = 10

Programa 3: haciendo uso del operador XOR bit a bit:

El operador XOR bit a bit se puede utilizar para intercambiar dos variables. El XOR de dos números xey devuelve un número que tiene todos los bits como 1 siempre que los bits de xey difieran. Por ejemplo, XOR de 10 (en binario 1010) y 5 (en binario 0101) es 1111 y XOR de 7 (0111) y 5 (0101) es (0010).

#include <stdio.h>
int main()
{
 int x = 10, y = 5;
 // Code to swap 'x' (1010) and 'y' (0101)
 x = x ^ y;  // x now becomes 15 (1111)
 y = x ^ y;  // y becomes 10 (1010)
 x = x ^ y;  // x becomes 5 (0101)
 printf("After Swapping: x = %d, y = %d", x, y);
 return 0;

Salida:

Después del intercambio: x = 5, y = 10

Programa 4:

Nadie ha sugerido usar std :: swap, todavía.

std::swap(a, b);

No utilizo ninguna variable temporal y, dependiendo del tipo de ayb, la implementación puede tener una especialización que tampoco. La implementación debe escribirse sabiendo si un 'truco' es apropiado o no.

Problemas con los métodos anteriores:

1) El método basado en la multiplicación y la división no funciona si uno de los números es 0, ya que el producto se convierte en 0 independientemente del otro número.

2) Ambas soluciones aritméticas pueden provocar un desbordamiento aritmético. Si xey son demasiado grandes, la suma y la multiplicación pueden salirse del rango de números enteros.

3) Cuando usamos punteros a una variable y hacemos un intercambio de función, todos los métodos anteriores fallan cuando ambos punteros apuntan a la misma variable. Echemos un vistazo a lo que sucederá en este caso si ambos apuntan a la misma variable.

// Método basado en XOR bit a bit

x = x ^ x; // x becomes 0
x = x ^ x; // x remains 0
x = x ^ x; // x remains 0

// Método basado en aritmética

x = x + x; // x becomes 2x
x = x  x; // x becomes 0
x = x  x; // x remains 0

Veamos el siguiente programa.

#include <stdio.h>
void swap(int *xp, int *yp)
{
    *xp = *xp ^ *yp;
    *yp = *xp ^ *yp;
    *xp = *xp ^ *yp;
}

int main()
{
  int x = 10;
  swap(&x, &x);
  printf("After swap(&x, &x): x = %d", x);
  return 0;
}

Salida :

Después del intercambio (& x, & x): x = 0

Es posible que sea necesario intercambiar una variable consigo misma en muchos algoritmos estándar. Por ejemplo, vea esta implementación de QuickSort donde podemos intercambiar una variable consigo misma. El problema anterior se puede evitar poniendo una condición antes del intercambio.

#include <stdio.h>
void swap(int *xp, int *yp)
{
    if (xp == yp) // Check if the two addresses are same
      return;
    *xp = *xp + *yp;
    *yp = *xp - *yp;
    *xp = *xp - *yp;
}
int main()
{
  int x = 10;
  swap(&x, &x);
  printf("After swap(&x, &x): x = %d", x);
  return 0;
}

Salida :

Después del intercambio (& x, & x): x = 10

shobhit2905
fuente
0

Quizás fuera del tema, pero si sabe lo que está intercambiando una sola variable entre dos valores diferentes, es posible que pueda hacer una lógica de matriz. Cada vez que se ejecuta esta línea de código, cambiará el valor entre 1 y 2.

n = [2, 1][n - 1]
quemeful
fuente
0

Podrías hacerlo:

std::tie(x, y) = std::make_pair(y, x);

O use make_tuple cuando intercambie más de dos variables:

std::tie(x, y, z) = std::make_tuple(y, z, x);

¡Pero no estoy seguro de si internamente std :: tie usa una variable temporal o no!

pooya13
fuente
0

En javascript:

function swapInPlace(obj) {
    obj.x ^= obj.y
    obj.y ^= obj.x
    obj.x ^= obj.y
}

function swap(obj) {
    let temp = obj.x
    obj.x = obj.y
    obj.y = temp
}

Tenga en cuenta el tiempo de ejecución de ambas opciones.

Al ejecutar este código, lo medí.

console.time('swapInPlace')
swapInPlace({x:1, y:2})
console.timeEnd('swapInPlace') // swapInPlace: 0.056884765625ms

console.time('swap')
swap({x:3, y:6})
console.timeEnd('swap')        // swap: 0.01416015625ms

Como puede ver (y como muchos dijeron), el intercambio en el lugar (xor) toma mucho tiempo que la otra opción que usa la variable temporal.

ofir_aghai
fuente
0

A R le falta una asignación concurrente propuesta por Edsger W. Dijkstra en A Discipline of Programming , 1976, cap.4, p.29. Esto permitiría una solución elegante:

a, b    <- b, a         # swap
a, b, c <- c, a, b      # rotate right
user3604103
fuente
-1
a = a + b - (b=a);

Es muy simple, pero puede generar una advertencia.

alsimoneau
fuente
5
¿La advertencia es que no funciona? No sabemos si b=ase realiza antes o después a + b.
Bo Persson
-1

solución de una sola línea para intercambiar dos valores en lenguaje c.

a=(b=(a=a+b,a-b),a-b);
HARITUSH
fuente
Comportamiento indefinido en caso de desbordamiento.
Keith Thompson
-1
second_value -= first_value;
first_value +=  second_value;
second_value -= first_value;
second_value *= -1;
Zikria Qureshi
fuente
Esto tiene un comportamiento indefinido si alguna de las operaciones se desborda o se desborda. También puede perder precisión si los objetos son de punto flotante.
Keith Thompson