Почему функция scanf ожидает тип указателя в C?

Я пишу код 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).

Спасибо за любые обсуждения!

Некоторое замечание для улучшения дальнейших вопросов: Если вы спрашиваете о конкретной функции, принимающей определенные параметры, то совершенно не важно, что должна делать программа. Нет необходимости добавлять эту диаграмму конечного автомата. Кроме того, для MCVE вам не нужно это определение структуры или этот массив и т. д. Удалите все, что не дает никакого дополнительного значения для примера. Детали, которые не требуются, только отвлекают людей, читающих ваш вопрос.

Gerhardh 17.11.2022 05:51
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
1
59
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

О, это не 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 17.11.2022 18:40

@user2874626 user2874626 пожалуйста ... Если это решит вашу проблему, не стесняйтесь ставить «галочку» одобрения. Обратите внимание, что при использовании директивы scanfs %s массив char, который мы передаем, является подходящим ссылочным типом, поэтому в этом случае вам не нужен (и, вероятно, не следует использовать) амперсанд... int test(char fubar[]) { /* ... and any modifications we make to fubar[X] are visible to the caller */ }... Это всего лишь для тех примитивных нессылочных типов, которые нам нужно упаковать с помощью указателя, как мы могли бы в Java (поэтому вместо передачи целого числа мы могли бы передать массив из одного целого числа и т. д.).

autistic 17.11.2022 22:28

Я отметил твой ответ. :) Спасибо вам за разъяснение! C кажется более сложным, чем C++ в указателях...

user2874626 18.11.2022 18:24

Другие вопросы по теме