web-dev-qa-db-fra.com

Existe-t-il une fonction d’échange intégrée en C?

Existe-t-il une fonction d’échange intégrée en C qui fonctionne sans utiliser une troisième variable?

29
user1149207

Non.
C++ a mais cela fonctionne comme c = a;a = b; b = c;
Fonction swap intégrée à C++: swap(first,second);
.__ Vérifiez ceci: http://www.cplusplus.com/reference/algorithm/swap/

Vous pouvez l'utiliser pour échanger la valeur de deux variables sans utiliser la troisième variable: 

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

Vous pouvez aussi vérifier ceci:

https://stackoverflow.com/questions/756750/swap-the-values-of-two-variables-without-using-third-variable

Comment échanger sans une troisième variable?

24
Saif

Pourquoi ne voulez-vous pas utiliser une troisième variable? C'est le moyen le plus rapide sur la grande majorité des architectures.

L'algorithme de swap XOR fonctionne sans troisième variable, mais pose deux problèmes:

  1. Les variables doivent être distinctes, c'est-à-dire que swap(&a, &a) ne fonctionnera pas.
  2. C'est plus lent en général.

Il peut parfois être préférable d’utiliser le swap XOR si l’utilisation d’une troisième variable ferait déborder la pile, mais vous n’êtes généralement pas en mesure de le faire.

Pour répondre directement à votre question, non, il n’existe pas de fonction d’échange en C standard, bien qu’il soit facile d’écrire.

23
Peter Alexander

Il n'y a pas de telle fonction dans la norme C.

(En C++, vous avez std::swap() .)


Peut-être qu'une macro de cette question peut vous être utile.

8
Igor Oks

En supposant que vous souhaitiez unCsolotion, pas un C++ one, vous pouvez en faire une macro, au moins en utilisant l’extension GCC pour qu’elle soit assez générique, quelque chose comme

 #define SWAP(x,y) do {   \ 
   typeof(x) _x = x;      \
   typeof(y) _y = y;      \
   x = _y;                \
   y = _x;                \
 } while(0)

méfiez-vous des astuces telles que les invocations swap(t[i++],i); pour les éviter, utilisez l'opérateur d'adresse &. Et vous ferez mieux d'utiliser un temporaire (pour les entiers, il existe un truc célèbre et inutile avec exclusive-ou).

PS: J'utilise deux variables locales _x et _y (mais j'aurais pu utiliser une seule variable locale) pour une meilleure lisibilité, et peut-être aussi pour permettre davantage d'optimisations à partir du compilateur.

8

Il n'y a pas de fonction standard en C pour échanger deux variables.

Une macro peut être écrite de cette façon:

#define SWAP(T, a, b) do { T tmp = a; a = b; b = tmp; } while (0)

et la macro peut être appelée de cette façon:

int a = 42;
int b = 2718;

SWAP(int, a, b);

Certaines solutions pour l'écriture d'une macro SWAP doivent être évitées:

#define SWAP(a, b) do { a = b + a; b = a - b; a = a - b; } while (0)

lorsque les opérandes sont de types signés, un débordement peut survenir et le débordement signé est un comportement non défini.

Une solution essayant d'optimiser la solution XOR comme celle-ci devrait également être évitée:

#define SWAP(a, b) (a ^= b ^= a ^=b)

a est modifié deux fois entre le point de séquence précédent et le suivant, de sorte qu'il enfreint les règles de point de séquence et constitue un comportement indéfini.

6
ouah

Comme vous pouvez copier n'importe quelle représentation d'objet dans un tableau de caractères non signé en C, la macro suivante vous permet d'échanger deux objets:

#define SWAP(X,Y) \
    do { \
        unsigned char _buf[sizeof(*(X))]; \
        memmove(_buf, (X), sizeof(_buf)); \
        memmove((X),  (Y), sizeof(_buf)); \
        memmove((Y), _buf, sizeof(_buf)); \
    } while (0)

GCC générera même un code optimal pour cela dans certains cas. Vous pourriez ne pas garder votre travail cependant ...

2
u0b34a0f6ae

Il n'y a pas de fonction swap intégrée mais vous pouvez essayer ceci

a = a ^ b;

b = a ^ b;

a = b ^ a;

1
Saif

Il existe une fonction de bibliothèque C++. Il échange les valeurs de deux variables entières. Par exemple, swap (x, y); échangera les valeurs des variables x et y. De même, swap (mat [i] [j], mat [j] [i]); échangera deux valeurs dans la matrice, à savoir la valeur de la ligne i, colonne j et la valeur de la ligne j, colonne i.

1
Prinavin Govender

Je pense avoir mis au point une fonction de type agnostique pour échanger deux valeurs de la norme C, bien que, comme je suis assez novice dans cette langue, j'ai peut-être oublié quelque chose. Il utilise l'algorithme d'échange XOR, et je suis sûr qu'il pourrait être optimisé davantage, mais cela fonctionne tant que les deux valeurs pointent vers le même nombre d'octets, spécifié par le 3ème argument:

void swapn(void *a, void *b, size_t n) {
    if (a == b) {
        return;
    }

    size_t i;
    char *x = (char *)a,
        *y = (char *)b;

    for (i = 0; i < n; i++) {
        *x ^= *y;
        *y ^= *x;
        *x ^= *y;
        x++;
        y++;
    }
}

Exemple d'utilisation:

// swap two integers
int x = 5,
    y = 30;

printf("%d\t%d\n", x, y);

swapn(&x, &y, sizeof(int));

printf("%d\t%d\n\n", x, y);

// swap two floats
float a = 9.23f,
    b = 6.83f;

printf("%.2f\t%.2f\n", a, b);

swapn(&a, &b, sizeof(float));

printf("%.2f\t%.2f\n\n", a, b);

// swap two doubles
double p = 4.7539,
    q = 0.9841;

printf("%.4f\t%.4f\n", p, q);

swapn(&p, &q, sizeof(double));

printf("%.4f\t%.4f\n\n", p, q);

// swap two chars
char m = 'M',
    n = 'n';

printf("%c\t%c\n", m, n);

swapn(&m, &n, sizeof(char));

printf("%c\t%c\n\n", m, n);

// swap two strings of equivalent length
char s[] = "Hello",
    t[] = "World";

printf("%s\t%s\n", s, t);

swapn(s, t, sizeof(s));

printf("%s\t%s\n\n", s, t);

La sortie est:

5   30
30  5

9.23    6.83
6.83    9.23

4.7539  0.9841
0.9841  4.7539

M   n
n   M

Hello   World
World   Hello
0
Patrick Roberts
#define swap(T, x, y) \
    {                 \
        T tmp = x;    \
        x = y;        \
        y = tmp;      \
    }

int main()
{
    int a = 10;
    int b = 20;
    printf("a=%d b=%d\n", a, b);
    swap(int, a, b);
    printf("a=%d b=%d\n", a, b);

    return 0;
}
0
Li Kui

il y a std::swap car en général, cela dépend de votre processeur, de la prise en charge de l’échange. Il existe une instruction appelée "comparer et échanger", mais elle ne fonctionne que sur les types qui entrent dans un registre et qui est garantie d'être atomique. Il existe une implémentation intégrée de compare et swap (CAS) à partir de gcc . Elle est utilisée pour la synchronisation des implémentations de threads et de mutex. Elle est probablement hors de portée. si vous êtes vraiment bloqué sur C, vous pouvez toujours utiliser une macro comme celle-ci:

#define swap(a,b) a=a^b; \
                  b=a^b; \
                  a=b^a;
0
Alex