Функция подстановки общего типа c - PullRequest
0 голосов
/ 01 декабря 2019

Я пытаюсь написать простую функцию, которая будет заменять любые две переменные одного типа.

void swap(void* a, void* b, int size);

void swap(void* a, void* b, int size){
    void* temp = malloc(size);

    memcpy(temp, a,size);

    memcpy(a, b, size);

    memcpy(b, temp,size);

    free(temp);
}

int main(int argc, char* argv[])
{
    char name[] = "name";
    char greet[] = "greet";

    swap(name, greet, 30);

    printf("%s\n", name);
    printf("%s\n", greet);

    return 0;
}

Но то, что напечатано в приведенном выше коде:

`
name

значение, на которое указывает a (в swap), изменяется на `после memcpy (b, temp, size), я не уверен, почему?

Ответы [ 3 ]

0 голосов
/ 01 декабря 2019

Есть некоторые ошибки, приводящие к неопределенному поведению. 1. Вы копируете 30 байтов из массива, длина которого составляет 5 байтов («имя» - это 4 символа + 1 байт в конце 0). 2. Вы копируете 30 байтов в массив длиной 6 байтов ("приветствие" - 5 символов + 1 байт в конце 0). Обе ошибки могут вызвать проблему, особенно вторую: вы пытаетесь использовать 24 байта памяти за пределами массива - невозможно определить результаты этого.

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

0 голосов
/ 01 декабря 2019

Как отмечается в комментариях, вы не можете поменять местами greet и name, поскольку их типы не совпадают: char[6], против char[5] (включая завершающий NUL), и они имеют другой размер.

Тем не менее, swap может использоваться на объекте char *, поскольку массив char может быть преобразован в char *, изменение простое.

int main(int argc, char* argv[])

    char name[] = "name";
    char greet[] = "greet";

    char *p1 = name ;
    char *p2 = greet ;

    swap(&p1, &p2, sizeof(p1)) ;

    printf("%s\n", p1);
    printf("%s\n", p2);
}

Примечание: нет необходимости использовать malloc для временного пространства, если вы не собираетесь перемещать очень большие объекты. Просто char temp[size] ; сделает работу - вместо malloc - и не нужно освобождать (и незначительное увеличение производительности).

0 голосов
/ 01 декабря 2019

Когда вы вызываете memcpy(b, temp,size); с размером, равным 30, и фактическим размером строки, на который указывает b, равным 6, вы в основном пишете за пределы своей памяти.

В вашем случае ваша программа фактически повредит программный стек. Если в памяти b предшествует a, дополнительные 24 будут эффективно перезаписывать содержимое a полностью.

Необходимо проверить, меньше или равно size наименьший размеробе строки + 1 (для учета нулевого символа).

...