1
\$\begingroup\$

In AVR-libc page 143 the implementation of the function uart_putchar() is typical as the following:

#include <stdio.h>
static int uart_putchar(char c, FILE *stream);
static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE);
static int
uart_putchar(char c, FILE *stream)
{
if (c == '\n')
 uart_putchar('\r', stream);
loop_until_bit_is_set(UCSRA, UDRE);
UDR = c;
return 0;
}
int
main(void)
{
 init_uart();
 stdout = &mystdout;
 printf("Hello, world!\n");
 return 0;
}

I know that we can redirect a specific stream to a stdout or stdin using fdevopen().

But is not the variable stream is not used in this function? Why is there such a variable that not used by the function? Is that because the fdevopen() pointers to functions parameters?

asked Feb 19, 2022 at 10:52
\$\endgroup\$
0

2 Answers 2

2
\$\begingroup\$

You are not specifically creating a UART stream. You are creating a generic stream that happens to go to the UART.

Many times streams can go to different places. As the variable type FILE suggests it's commonly to a file - such as on an SD card. In these situations the FILE parameter is essential for the function to know exactly where the data is to go to.

For the UART it is irrelevant since there is only one place it can go - the UART.

The functions that interact with whatever you implement expect a certain prototype and pass certain parameters. Whether you use those parameters or not you have to accept them and have them in your function prototype - otherwise you just can't compile your code (you have a mismatch in the function pointer definitions).

answered Feb 19, 2022 at 12:25
\$\endgroup\$
2
  • 1
    \$\begingroup\$ Shouldn't the compiler throw a warning at compile time because of that unused variable? \$\endgroup\$ Commented Feb 19, 2022 at 13:04
  • 1
    \$\begingroup\$ @NAND It is used in this case - it's passed to the recursive line feed / cr call. Plus not all compilers have it turned on by default. \$\endgroup\$ Commented Feb 19, 2022 at 13:24
1
\$\begingroup\$

Why is there such a variable that not used by the function?

The first parameter of fdevopen takes a parameter of type

int (*)(char, FILE*)

which is a pointer to a function that returns int and which takes two arguments: One of type char and then one of type FILE*.

Consequently, when providing (the address of) a putter function to fdevopen, that function must have the same signature, even if some argument is unused. Same applies to the first argument of FDEV_SETUP_STREAM, which is used to initialize some FILE object, and where the respective component also has that type.

Strictly speaking, parameter stream is used in the example because it is passed down to a self-call of uart_putchar. If it was really unused, you could do the following:

  • C++: Omit the parameter name like in int uart_putchar (char c, FILE*) { ... }
  • C++17, C23: Mark the parameter with attribute [[maybe_unused]].
  • GNU-C, GNU-C++: Mark the parameter with __attribute__((__unused__)).
  • Add a line (void) stream;.

All these means tell a reader that the parameter is unused, and they tell the compiler that it's fine that the parameter is unused so the compiler will not throw a diagnostic at you.

answered Nov 30, 2023 at 21:15
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.