Aus '\n' wird '\0'

OP #4122059
Lesenswert?
• ▲
▼
Hallo zusammen,
ich nutze gerade den ARM-GCC und habe folgende, wahnsinnig komplizierte 
Funktion:
1
void printme(void)
2
{
3
    printf("\fPWM test PC9\n");
4
    printf("PWM test PC9\n"); // |<-- der Ausdruck muss genauso bleiben.
5
}
Schaue ich mir die Zeichenkette im Binary an, steht da allerdings:
1
0000A7F0  00 00 00 00 0C 50 57 4D 20 74 65 73 74 20 50 43  .....PWM test PC
2
0000A800  39 00 00 00 50 57 4D 20 74 65 73 74 20 50 43 39  9...PWM test PC9
d.h. das Newline am Ende wird zu einem '\0' gemacht.

Deshalb meine an die Wissenden:

 - Handelt es sich um gewünschtes Verhalten (irgendeine schwierig zu 
findende Definition von printf) ?

 - Wie kann ich den Compiler dazu bringen, das zu machen, was ich bei 
obigem Quelltext naiv erwartet hätte? Der Umbruch muß im oberen String 
bleiben. Momentan behelfe ich mir mit:
1
    printf("\fPWM test PC9\n \b");
2
    printf("PWM test PC9\n");

Viele Grüße
W.T.
OP #4122079
Lesenswert?
• ▲
▼
Hallo zusammen,

Rufus Τ. Firefly schrieb:
> und puts hängt das abschließende \n selbst an.

danke für die Erinnerung! Das wird es sein.

g457 schrieb:
> Hast Du puts() selbst implementiert? Falls ja isses kaputt, falls nein
> höchstwahrscheinlich auch :-)

Ja, die Implementierung der stdio-Funktionen etwas kaputt. Nicht nur an 
dieser Stelle. (z.B. spielt sie total verrückt, wenn eine Zeichenkette 
mit nur einem Zeichen mit printf ausgegeben wird oder das 
Leerzeichen-Flag zur Formatierung verwendet wird). Sie lag CooCox bei.

Und so sieht sie aus:
1
/**
2
 * @brief  Outputs a string on stdout.
3
 *
4
 * @param pStr  String to output. 
5
 */
6
signed int puts(const char *pStr)
7
{
8
    return fputs(pStr, stdout);
9
}
10

11

12
/**
13
 * @brief  Implementation of fputs using the DBGU as the standard output. Required
14
 *         for printf().
15
 *
16
 * @param pStr     String to write.
17
 * @param pStream  Output stream.
18
 *
19
 * @return  Number of characters written if successful, or -1 if the output
20
 *          stream is not stdout or stderr.
21
 */
22
signed int fputs(const char *pStr, FILE *pStream)
23
{
24
    signed int num = 0;
25

26
    while (*pStr != 0) {
27

28
        if (fputc(*pStr, pStream) == -1) {
29

30
            return -1;
31
        }
32
        num++;
33
        pStr++;
34
    }
35

36
    return num;
37
}

Dann werde ich mal puts oder fputs (muß mal nachsehen, wer das 
Leerzeichen normalerweise erzeugt) entsprechend ergänzen. Danke fürs 
Lesen und die Ratschläge.

W.T.
#4122101
Lesenswert?
• ▲
▼
@ Walter Tarpan (nicolas)

>{
>    printf("\fPWM test PC9\n");
>    printf("PWM test PC9\n"); // |<-- der Ausdruck muss genauso bleiben.
>}

>0000A7F0  00 00 00 00 0C 50 57 4D 20 74 65 73 74 20 50 43  .....PWM test PC
>0000A800  39 00 00 00 50 57 4D 20 74 65 73 74 20 50 43 39  9...PWM test PC9

>d.h. das Newline am Ende wird zu einem '\0' gemacht.

Dann ist printf() ein Makro, das einen String vor dem echten Compilieren 
konvertiert und das \n entfernt. Ein normaler Compiler schmeißt das \n 
nicht raus.
#4122107
Lesenswert?
• ▲
▼
Mal eine blöde Frage zu den Optimierungsmöglichkeiten eines Compilers.
Wenn man grundsätzlich eine Optimierung möchte, aber an bestimmten 
Punkten nicht, kann man das ins Programm schreiben, bzw. gibt es ein 
Möglichkeit dem Compiler das mitzuteilen, so wie bei sei () und cli () 
für die Interrupts?
Moderator #4122286
Lesenswert?
• ▲
▼
Falk Brunner schrieb:
> Dann ist printf() ein Makro, das einen String vor dem echten Compilieren
> konvertiert und das \n entfernt.

Genauer gesagt, ist es eine eine Built-In-Funktion des GCC. Solche
Built-In-Versionen gibt es auch für viele andere Funktionen aus der
Standardbibliothek und sind eigentlich eine feine Sache, da sie dem
Compiler Optimierungsmöglichkeiten eröffnen, die er ohne sie nicht 
hätte.

Sollten sie doch einmal stören, lassen sie sich mit -fno-builtin oder
-fno-builtin-<funktionsname> abschalten.

> Ein normaler Compiler schmeißt das \n nicht raus.

Was ist heutzutage noch normal? ;-)
#4122308
Lesenswert?
• ▲
▼
@ Yalu X. (yalu) (Moderator)

>> Dann ist printf() ein Makro, das einen String vor dem echten Compilieren
>> konvertiert und das \n entfernt.

>Genauer gesagt, ist es eine eine Built-In-Funktion des GCC.

Aber das normale printf() im avr gcc schmeißt das \n doch nicht raus, 
oder?
Moderator #4122350
Lesenswert?
• ▲
▼
Das \n wird nur dann hinausgeschmissen, wenn der Compiler den printf-
durch einen puts-Aufruf ersetzt, da puts im Gegensatz zu printf die
Ausgabe schon von sich aus mit einem \n abschließt. Am Verhalten des
Programms ändert sich dadurch überhaupt nichts.

Anderes Beispiel:
1
  printf("X");

wird vom GCC in
1
  putchar('X');

umgesetzt.

In diesem Fall fällt sogar die komplette Stringkonstante weg,
stattdessen wird der Zeichencode von 'X' direkt als Argument übergeben.

Antwort schreiben

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.