Есть ли встроенная функция подкачки в C? - PullRequest
33 голосов
/ 14 января 2012

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

Ответы [ 11 ]

27 голосов
/ 14 января 2012

Нет.
C ++ имеет, но работает как c = a;a = b; b = c;
Встроенная функция обмена 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

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

24 голосов
/ 14 января 2012

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

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

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

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

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

8 голосов
/ 14 января 2012

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

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

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

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

8 голосов
/ 14 января 2012

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

(в C ++ у вас есть std::swap().)


Может быть, макрос из этот вопрос может быть полезен для вас.

6 голосов
/ 14 января 2012

В 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)

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

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

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

2 голосов
/ 13 января 2013

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

1 голос
/ 18 сентября 2014

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

1 голос
/ 27 августа 2012

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

a = a ^ b;

b = a ^ b;

a = b ^ a;

0 голосов
/ 16 июля 2018
#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 голосов
/ 07 марта 2015

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

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
...