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