Подтвердить что ты не робот

Есть ли встроенная функция свопинга в C?

Есть ли встроенная функция swap в C, которая работает без использования третьей переменной?

4b9b3361

Ответ 1

Нет.
С++ имеет, но работает как c = a;a = b; b = c;
С++ встроенная функция подкачки: swap(first,second);
Проверьте это: http://www.cplusplus.com/reference/algorithm/swap/

Вы можете использовать это для замены двух значений переменной без использования третьей переменной:

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

Вы также можете проверить это:

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

Как поменять местами без третьей переменной?

Ответ 2

Почему вы не хотите использовать третью переменную? Это самый быстрый путь на подавляющем большинстве архитектур.

алгоритм обмена XOR работает без третьей переменной, но это проблематично двумя способами:

  • Переменные должны быть различны, т.е. swap(&a, &a) не будет работать.
  • В целом он медленнее.

Иногда может быть предпочтительнее использовать замену XOR, если использование третьей переменной вызовет утечку стека, но обычно вы не в таком положении, чтобы сделать этот вызов.

Чтобы ответить на ваш вопрос напрямую, нет никакой функции подкачки в стандарте C, хотя было бы тривиально писать.

Ответ 3

Предполагая, что вы хотите соло-ние C, а не С++, вы можете сделать его макросом, по крайней мере используя расширение GCC, чтобы оно было достаточно общим, что-то вроде

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

остерегайтесь трюков, таких как invocations swap(t[i++],i); чтобы избежать их, используйте адресный оператор &. И вам лучше использовать временную (для целых чисел, есть знаменитый и бесполезный трюк с эксклюзивным или).

PS: Я использую две локальные переменные _x и _y (но я мог использовать только одну локальную переменную) для лучшей читаемости и, возможно, также для включения большего количества оптимизаций из компилятора.

Ответ 4

В стандарте C такой функции нет.

(В С++ у вас std::swap().)


Возможно, вам может быть полезен макрос этого вопроса.

Ответ 5

В C нет стандартной функции для замены двух переменных.

Макрос можно записать следующим образом:

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

и макрос можно вызвать следующим образом:

int a = 42;
int b = 2718;

SWAP(int, a, b);

Следует избегать некоторых решений для написания макроса SWAP:

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

когда операнды имеют подписанные типы, может произойти переполнение, а переполнение подписей - поведение undefined.

Также следует избегать решения, пытающегося оптимизировать решение XOR следующим образом:

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

a изменяется дважды между предыдущей и следующей точками последовательности, поэтому он нарушает правила точек последовательности и выполняет поведение undefined.

Ответ 6

Поскольку вы можете скопировать любое представление объекта в массив без знака char в C, следующий макрос позволяет вам обменивать любые два объекта:

#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 будет генерировать оптимальный код для этого. Возможно, вы не сохранили свою работу, хотя...

Ответ 7

Нет встроенной функции свопинга, но вы можете попробовать это

a = a ^ b;

b = a ^ b;

a = b ^ a;

Ответ 8

Существует функция библиотеки С++. Он меняет значения двух целых переменных. Например, swap (x, y); будет менять значения переменных x и y. Аналогично, swap (мат [i] [j], мат [j] [i]); будет заменять два значения в матричном мат, а именно на значение в столбце j строки я и значение в столбце j строки.

Ответ 9

существует std::swap, так как в целом это зависит от вашего процессора, поддерживает ли он swaping. есть инструкция, называемая "сравнивать и заменять", но она работает только с типами, которые вписываются в регистр и гарантированно являются атомарными. Существует встроенная реализация сравнения и свопинга (CAS) из gcc, которая используется для синхронизации реализаций потоков и мьютексов и, вероятно, выхода возможностей для вашей цели, поэтому лучше всего использовать только временную переменную или если вы действительно привязаны к C, вы всегда можете использовать макрос, как это:

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

Ответ 10

Я считаю, что я придумал функцию типа-агностика для замены любых двух значений в стандартном C, хотя, поскольку я довольно новичок в языке, я, возможно, что-то упустил. Он использует алгоритм замены XOR, и я уверен, что он может быть оптимизирован больше, но он работает до тех пор, пока два значения указывают на то же количество байтов, указанное третьим аргументом:

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

Пример использования:

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

Вывод:

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