Forum: Mikrocontroller und Digitale Elektronik deprecated conversion


von Georg M. (g_m)


Lesenswert?

Demo Code von Microchip Technology Incorporated:
1
/* ----------------------------------------------------------------
2
Demo Code
3
This code example is used to continuously send the 'Hello World!' string through USART. A string is sent character by character. The ‘USART1_sendString’ function calls the ‘USART1_sendChar’ function for each character in the ‘Hello Word!’ string. Before sending each character, the ‘USART1_sendChar’ function waits for the previous character transmission to be completed. This is done by polling the Data Register Empty Interrupt Flag, DREIF, from the STATUS register until it is set.
4
------------------------------------------------------------------*/
5
#define F_CPU 3333333
6
#define USART1_BAUD_RATE(BAUD_RATE) ((float)(F_CPU * 64 / (16 * (float)BAUD_RATE)) + 0.5)
7
#include <avr/io.h>
8
#include <util/delay.h>
9
#include <string.h>
10
void USART1_init(void);
11
void USART1_sendChar(char c);
12
void USART1_sendString(char *str);
13
void USART1_init(void)
14
{
15
 PORTC.DIR &= ~PIN1_bm;
16
 PORTC.DIR |= PIN0_bm;
17
 
18
 USART1.BAUD = (uint16_t)USART1_BAUD_RATE(9600);
19
 USART1.CTRLB |= USART_TXEN_bm;
20
}
21
void USART1_sendChar(char c)
22
{
23
 while (!(USART1.STATUS & USART_DREIF_bm))
24
 {
25
  ;
26
 } 
27
 USART1.TXDATAL = c;
28
}
29
void USART1_sendString(char *str)
30
{
31
 for(size_t i = 0; i < strlen(str); i++)
32
 {
33
  USART1_sendChar(str[i]);
34
 }
35
}
36
int main(void)
37
{
38
 USART1_init();
39
 
40
 while (1)
41
 {
42
  USART1_sendString("Hello World!\r\n");
43
  _delay_ms(500);
44
 }
45
}
https://ww1.microchip.com/downloads/en/Appnotes/TB3216-Getting-Started-with-USART-DS90003216.pdf

Der Compiler von Microchip Technology Incorporated bemängelt aber die 
Zeile
1
 USART1_sendString("Hello World!\r\n");
mit
1
Warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]

Wie wäre es dann richtiger?

von Mombert H. (mh_mh)


Lesenswert?

sendString braucht offensichtlich ein const also: char const*

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Richtig wäre es, wenn "USART1_sendString" ein Argument vom Typ "const 
char*" übernehmen würde. Schließlich sollte es den Text nicht verändern.
1
void USART1_sendString(const char *str)
2
{
3
 for(size_t i = 0; i < strlen(str); i++)
4
 {
5
  USART1_sendChar(str[i]);
6
 }
7
}

Allerdings wird hier strlen in jedem Durchlauf aufgerufen, d.h. super 
ineffizient. Viel besser geht es so:
1
void USART1_sendString(const char *str)
2
{
3
 for(const char* p = str; *p != '\0'; ++p)
4
 {
5
  USART1_sendChar(*p);
6
 }
7
}

Weil es ja um AVR geht, wäre es natürlich noch besser den String nur im 
Flash abzulegen.

Falls du mal den Fall hast dass du eine Funktion wie USART1_sendChar 
hast die den String tatsächlich ändert, muss man eine Kopie des Strings 
im RAM (hier: auf dem Stack) anlegen:
1
char str [] = "Hello World!\r\n";
2
USART1_sendString(str);

Hier ist also wieder schön zu sehen, dass die Mikrocontroller-Hersteller 
desaströse Code-Qualität produzieren, und Microchip ist ganz vorne 
dabei.

: Bearbeitet durch User
von Mombert H. (mh_mh)


Lesenswert?

Niklas G. schrieb:
> Allerdings wird hier strlen in jedem Durchlauf aufgerufen, d.h. super
> ineffizient.

Ab welcher Stringlänge fängt das an ineffizient zu werden, wenn die 
Baudrate 9600 ist?

Niklas G. schrieb:
> Hier ist also wieder schön zu sehen, dass die Mikrocontroller-Hersteller
> desaströse Code-Qualität produzieren, und Microchip ist ganz vorne
> dabei.
Das ist bei diesem Beispiel etwas übertrieben.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.