Я пишу код c для реализации следующего конечного автомата: (от ТИ-РСЛК). Вот, пожалуйста, найдите код:
#include <stdio.h>
struct state{
unsigned int output;
unsigned int delay;
const struct state *next[4];
};
#define center &fsm[0]
#define left &fsm[1]
#define right &fsm[2]
typedef const struct state state_t;
state_t fsm[3] = {
{3, 50, {right, left, right, center}},
{2, 50, {left, center, right, center}},
{1, 50, {right, left, center, center}}
};
int main(void)
{
state_t *spt;
unsigned int input;
unsigned int output;
spt = center;
while(1) {
output = spt->output;
printf("%u \n", output);
scanf("%u \n", input);
spt = spt->next[input];
}
printf("Hello World");
return 0;
}
Этот фрагмент кода вернет ошибку:
main.c: In function ‘main’:
main.c:37:17: warning: format ‘%u’ expects argument of type ‘unsigned int *’, but argument 2 has type ‘unsigned int’ [-Wformat=]
37 | scanf("%u \n", input);
| ~^ ~~~~~
| | |
| | unsigned int
| unsigned int *
3
Я думал, что '%u' принимает целое число без знака. Почему здесь имеется в виду указатель типа unsigned int?
Я также пробовал "%d". Я думал, что '%d' примет целое число. Ошибка также указывает на то, что ожидается указатель (типа integer).
Спасибо за любые обсуждения!
О, это не printf
ожидает указатель... Это scanf
, и причина ясна. Вы когда-нибудь пробовали написать функцию, которая изменяет свои аргументы таким образом, чтобы это было видно вызывающей стороне?
void test(int fubar) {
fubar = 42; // this doesn't work
}
Чтобы было ясно, scanf
должна иметь возможность назначать объект, который виден вызывающему, а C строго передается по значению (это означает, что аргументы копируются во временные местоположения), поэтому scanf
нужен ссылочный тип (например, указатель, передаваемый по значению, потому что C строго передает по значению), чтобы изменить то, на что ссылаются.
Вам не хватает амперсанда, и ваши scanf
порождают отвратительные догадки. Изменить это: scanf("%u \n", input);
К этому:
scanf("%u", &input);
// ^--- see?
... и возьмите копию K&R2e, чтобы вы могли прочитать ее и выполнить упражнения в спешке...
Спасибо за отличное объяснение. Я редко использую C, недавно узнал, что scanf принимает ссылочный тип. Я обновлю заголовок. :)
@user2874626 user2874626 пожалуйста ... Если это решит вашу проблему, не стесняйтесь ставить «галочку» одобрения. Обратите внимание, что при использовании директивы scanf
s %s
массив char
, который мы передаем, является подходящим ссылочным типом, поэтому в этом случае вам не нужен (и, вероятно, не следует использовать) амперсанд... int test(char fubar[]) { /* ... and any modifications we make to fubar[X] are visible to the caller */ }
... Это всего лишь для тех примитивных нессылочных типов, которые нам нужно упаковать с помощью указателя, как мы могли бы в Java (поэтому вместо передачи целого числа мы могли бы передать массив из одного целого числа и т. д.).
Я отметил твой ответ. :) Спасибо вам за разъяснение! C кажется более сложным, чем C++ в указателях...
Некоторое замечание для улучшения дальнейших вопросов: Если вы спрашиваете о конкретной функции, принимающей определенные параметры, то совершенно не важно, что должна делать программа. Нет необходимости добавлять эту диаграмму конечного автомата. Кроме того, для MCVE вам не нужно это определение структуры или этот массив и т. д. Удалите все, что не дает никакого дополнительного значения для примера. Детали, которые не требуются, только отвлекают людей, читающих ваш вопрос.