LINUX.ORG.RU

Передавай размер элемента третьим параметром.

d ★★★★★
()

Либо как сказали выше передавай размер, чтобы аллоцировать временный буфер, куда сложить a, потом в a b и в b временный буфер. Не забудь освободить.

Либо макросней, но это вообще по другому и твой преподаватель скорее всего спросит в чём отличие. :)

a1batross ★★★★★
()
Ответ на: комментарий от a1batross

Не забудь учесть, что размер должен быть типа size_t, а не int. И не забудь про проверку результата malloc(). Желательно, чтобы функция возвращала значение, чтобы можно было вернуть код успеха/ошибки. Ну поставь assert’ы, что входные указатели не нулевые и не равны друг другу.

BackDoorLover
()
Ответ на: комментарий от a1batross

Какие еще аллокации в swap?

void swap (void* a, void* b, size_t n) {
    size_t buf_size = 64; // можно больше, можно меньше
    char buf[64];
    size_t m = n % buf_size;
    n /= buf_size;
    for (size_t i = 0; i < n; i++) {
        memcpy (buf, a, buf_size);
        memcpy (a, b, buf_size);
        memcpy (b, buf, buf_size);
    }
    memcpy (buf, a, m);
    memcpy (a, b, m);
    memcpy (b, buf, m);
}

Проверки сам допишешь.

Siborgium ★★★★★
()
Последнее исправление: Siborgium (всего исправлений: 1)
Ответ на: удаленный комментарий

Как написать SWAP для любых типов данных на C

Для базовых типов данных?

Ну допустим есть такая структура:

struct Person {
  char *name; /* Dynamically allocated */
  struct {
    uint64_t length_meters;
    uint64_t diameter_meters;
  } Penis;
};

Какие ты видишь проблемы при memcpy() такой структуры?

BackDoorLover
()
Ответ на: комментарий от BackDoorLover

Еще раз, какие могут быть аллокации в swap?

Желательно, чтобы функция возвращала значение, чтобы можно было вернуть код успеха/ошибки.

Как может провалиться swap?

Siborgium ★★★★★
()
Ответ на: комментарий от Siborgium

Еще раз, какие могут быть аллокации в swap?

Кстати да, в C99 и выше можно без кучи обойтись

void f(size_t sz) {
  char buf[sz];
}

Как может провалиться swap?

Легко: передали нулевой указатель, а мы как давай его разыменовывать. Тут вам не кресты со ссылками, там да:

void swap(Penis &lhs, Penis &rhs) noexcept;
BackDoorLover
()
Ответ на: комментарий от Siborgium

Никаких проблем нет.

Вот и я о чём, поэтому и спросил анонимуса, почему он интересуется базовые типы, или нет.

BackDoorLover
()
Ответ на: комментарий от BackDoorLover

Кстати да, в C99 и выше можно без кучи обойтись

Еще раз, какая куча может быть в swap’е? VLA хотя и можно задействовать, но нет никакого смысла.

Легко: передали нулевой указатель, а мы как давай его разыменовывать.

А если острым себе в глаз ткнуть, что будет?

Siborgium ★★★★★
()
Ответ на: комментарий от Siborgium

VLA хотя и можно задействовать, но нет никакого смысла.

У нас sizeof(struct Penis) == 1024, ты ему char buf[64]. И что мы получили? Получили мы кусочек пениса, вместо полноценного штруя.

BackDoorLover
()
Ответ на: комментарий от BackDoorLover

Понятно. Когда человек не видит очевидной ошибки в коде, ему только и остается писать проверки.

Siborgium ★★★★★
()
Ответ на: комментарий от BackDoorLover

@vvediteima вот что преподавателю ответь

Чтобы менять местами пенисы покусочно нужен очень умелый хирург…
anonymous
()

В современном С есть возможность определить тип данных и вызвать в зависимости от типа нужную функцию.

Вот тебе прикол с дженериками:

#define FUNC(arg) _Generic(arg, uint16_t: funcu, int32_t: funci)(arg)

void funcu(uint16_t arg){
    printf("uint16_t: %u\n", arg);
}

void funci(int32_t arg){
    printf("int32_t: %d\n", arg);
}

int main(){
    uint16_t u = 32;
    int32_t i = -50333;
    FUNC(u);
    FUNC(i);
    return 0;
}
И таким образом ты можешь для всех десяти типов данных написать функцию обмена содержимым.

А еще можно просто макрос написать (в надежде, что не попадется разнотипных аргументов):

#define swap(a,b) {register typeof(a) t = a; a = b; b = t;}

anonymous
()
Ответ на: комментарий от anonymous

P.S. Bass, ты с головой дружишь? Как можно анонимуса призвать в закрытый для постинга анонимусом тред?

// Eddy_Em

anonymous
()
Ответ на: комментарий от anonymous

Да и вообще, меня всегда можно «скастовать», написав на мыло или отправив сообщение в пейсбуке, ЖЖшке, фконтактиге или ватсапе.

anonymous
()

@vvediteima вот что преподавателю ответь

Для того, чтобы поменять местами пенисы покусочно нужно знать их размер ...
anonymous
()
Ответ на: комментарий от anonymous

@vvediteima вот что преподавателю ответь

Для того, чтобы поменять местами пенисы покусочно нужно знать их размер, иначе не ... /"Гусарам молчать!"/ не получится
anonymous
()

Очевидно - нужен третий параметр, либо указатель на функцию, либо указатель на тип, либо размер. Но размер - это провал, т.к. структура может содержать указатели.

pon4ik ★★★★★
()
Последнее исправление: pon4ik (всего исправлений: 1)
Ответ на: комментарий от pon4ik

Очевидно - нужен третий параметр, либо указатель на функцию, либо указатель на тип, либо размер. Но размер - это провал, т.к. структура может содержать указатели.

Подолью масла в огонь.
А если структура к примеру vector содержит?

anonymous
()
Ответ на: комментарий от anonymous

В C нет векторов никаких!

А вот если там список, то с этим даже хваленые кресты не справятся! Все равно придется писать отдельную функцию для этого случая (но конкретно для свопа проще указатели местами поменять)!

anonymous
()
Ответ на: комментарий от anonymous

В C нет векторов никаких!

Вы правы

anonymous
()

Я таким макросом пользуюсь:

#define swap(Type, a, b) do         \
{                                   \
    Type *const _swpA = (a);        \
    Type *const _swpB = (b);        \
    Type const _swp = *_swpA;       \
    *_swpA = *_swpB, *_swpB = _swp; \
} while (0)

anonymous
()
Ответ на: комментарий от BackDoorLover

Какие ты видишь проблемы при memcpy() такой структуры?

Ну ты и слабенький, никаких проблем там не будет, указатели можно смело обменивать. Или ты собрался обменивать местами данные на которые указывает name🤣🤣🤣. Я же говорю, реально слабенький.

anonymous
()
Ответ на: комментарий от Siborgium

VLA хотя и можно задействовать

VLA же на стеке. Обязательно потом какой-нибудь долбодятел сунет sz=0xFFFFFFFFF и улетит в stack overflow.

Вот, например, без вообще без вызовов (а также проверок и оптимизаций)

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>

#define SWAP_BYTE(X,Y)   \
    do {                 \
        (X) = (X) ^ (Y); \
        (Y) = (X) ^ (Y); \
        (X) = (X) ^ (Y); \
    } while(0);

static inline void
swap_buffer (void* A, void* B, size_t sz) {
    uint8_t* B1 = (uint8_t*) A;
    uint8_t* B2 = (uint8_t*) B;
    
    for (uint32_t i = 0; i < sz; i++)
        SWAP_BYTE(B1[i],B2[i]);
}

int
main (int argc, char* argv[]) {
    int T1 = 12345, T2 = -456789;
    fprintf (stdout, "T1: %d\tT2: %d\n", T1, T2);
    swap_buffer (&T1,&T2, sizeof(int));
    fprintf (stdout, "T1: %d\tT2: %d\n", T1, T2);
    return 0;
}
SkyMaverick ★★★★★
()
Ответ на: комментарий от BackDoorLover

Это называется «стандартная херня, которую любой школьник знает, но в код тянут только мамкины какеры".

Полностью Согласен.

anonymous
()
Ответ на: комментарий от BackDoorLover

Это называется «стандартная херня, которую любой школьник знает».

Ага, а когда школьник выпускается из школы и идёт работать, ему объясняют, что кроме побайтной обработки этот код ещё и генерирует лишние чтения-записи на ровном месте.

i-rinat ★★★★★
()
Ответ на: комментарий от anonymous

Мне казалось, что так проще и наглядней, ну мне как минимум, и к тому же пример. swap через xor - неописуемый баян, который знают все, какое тут нафиг какерство.

SkyMaverick ★★★★★
()
Ответ на: комментарий от i-rinat

Ну я ж отметил, что и не претендовал на оптимальное решение.

SkyMaverick ★★★★★
()
Ответ на: комментарий от anonymous

Решается обоими двумя первыми вариантами. Двойная диспетчеризация будет реализована по разному, но быть собой от этого не перестанет.

pon4ik ★★★★★
()
Ответ на: комментарий от SkyMaverick

А если надо засвопить структуру вида:


struct node_st {
int handle;
size_t data_size;
void* data;
};

struct root_st {

int handle;
struct node_st* node;

};

?

pon4ik ★★★★★
()
Ответ на: комментарий от pon4ik

Здесь просто один буфер побайтово меняется с другим буфером. Без затей. Ссылки в списках оно ест-но не поменяет.

SkyMaverick ★★★★★
()
Ответ на: комментарий от RazrFalcon

Очевидно, что никак.

Ну раз местный эксперт по C сказал, что никак, то пора расходиться по домам.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.