Эта функция с указателями, по-видимому, не будет выполняться вообще

#c #function-call #function-declaration

#c #вызов функции #объявление функции

Вопрос:

Я пытаюсь создать программу, которая меняет местами 2 переменных в функции с побитовыми операторами, но функция ничего не сделает. Я почти уверен, что понял основную логику замены с помощью XOR правильно (я проверил, выполнив некоторые операции вручную, и проверил в main), но по какой-то причине функциональный блок просто ничего не сделает. Кроме того, я очень новичок в программировании на C, поэтому простите меня за то, что я не заметил какой-то очевидной глупой ошибки.

Код:

 #include <stdio.h>


void swap(int *a, int *b)
{
    printf("value of a=%d b=%d before swappingn", *a, *b);
    *a = *a ^ *b;
    *b = *a ^ *b;
    *a = *a ^ *b;
    printf("value of a=%d b=%d after swappingn", *a, *b);
}


int main()
{
    int a, b, *p, *q;
    printf("Enter 2 numbers to be swapped: n");
    scanf("%d %d", amp;a, amp;b);
    p = amp;a;
    q = amp;b;
    void swap(p, q);
    printf("nfinal %d %d", a, b);
}
 

Комментарии:

1. Вы могли бы исправить это, выполнив то, что сказал Passerby, но вы также можете использовать это как возможность улучшить свои навыки отладки: Шаг 1: Получаете ли вы какие-либо предупреждения при компиляции вашего кода с -Wall помощью? Если да, что это такое, и понимаете ли вы, что они означают? О, и добро пожаловать в SO, и поздравляем с хорошо написанным первым вопросом!

2. Приличный компилятор должен предупреждать вас об этом коде. Прослушивайте предупреждения, выдаваемые компилятором, и рассматривайте их как ошибки, которые необходимо исправить.

3. Да, я не понял предупреждения, которое выдал компилятор, и вроде как просто проигнорировал его… К счастью, Лундин специально указал на исправление, и оно исправлено! Я думаю, я пересмотрю функции.

Ответ №1:

gcc даже без -Wall указания точного местоположения ошибки. Просто скомпилируйте код и посмотрите, на что он указывает:

 warning: parameter names (without types) in function declaration
      |     void swap(p, q);
      |     ^~~~
 

Стрелка ^ с надписью «ошибка здесь». Просто отбросьте void его в вызове функции.

Кроме того, обмен XOR — это одна из тех вещей, которые «запутывают просто так». Единственной целью для этого, по-видимому, является создание, поскольку обмен временными переменными часто приводит к более эффективному коду. Смотрите Этот сравнительный анализ на x86 gcc -O3:

 void xor_swap(int *a, int *b)
{
    *a = *a ^ *b;
    *b = *a ^ *b;
    *a = *a ^ *b;
}

void tmp_swap(int *a, int *b)
{
  int tmp = *a;
  *a = *b;
  *b = tmp;
}

xor_swap:
        mov     eax, DWORD PTR [rdi]
        xor     eax, DWORD PTR [rsi]
        mov     DWORD PTR [rdi], eax
        xor     eax, DWORD PTR [rsi]
        mov     DWORD PTR [rsi], eax
        xor     DWORD PTR [rdi], eax
        ret

tmp_swap:
        mov     eax, DWORD PTR [rdi]
        mov     edx, DWORD PTR [rsi]
        mov     DWORD PTR [rdi], edx
        mov     DWORD PTR [rsi], eax
        ret
 

Она tmp_swap более удобочитаема и эффективна.


РЕДАКТИРОВАТЬ: на самом деле я только что немного поиграл с этим, и неэффективность версии XOR в основном исходит из предположений, что указатели могут быть псевдонимами. Обновление функции void xor_swap(int* restrict a, int* restrict b) сделало ее такой же быстрой, как tmp_swap и (но все еще менее читаемой).

Комментарии:

1. Также tmp_swap(a, b) все еще работает, когда a = b . xor_swap(a,b) функционально не удается поменять местами (данные обнуляются).

Ответ №2:

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

 void swap(p, q);
 

потому что это неверно.

Это объявление функции со списком идентификаторов, но в объявлении функции, которое одновременно не является ее определением, список идентификаторов должен быть пустым.

Вместо этого вам нужно вызвать функцию swap

 swap( p, q );
 

На самом деле указатели p и q являются избыточными. Вы также можете вызвать функцию, например

 swap( amp;a, amp;b );