Perché non C printf stringa di formato hanno entrambe %c e %s?

Perché non C printf stringa di formato hanno entrambi %c e %s?

So che %c rappresenta un singolo carattere e %s rappresenta una stringa con terminazione null caratteri, ma non sarebbe la rappresentazione in forma di stringa da solo essere sufficiente?

  • Probabilmente per distinguere tra di terminazione null stringa e un carattere. Se hanno appena avuto %s, poi ogni singolo personaggio deve essere di terminazione null. char c = ‘a’;, in questo caso c deve essere di terminazione null. Questa è la mia ipotesi, però 🙂
  • Perché non mettere che come una risposta, Soprattutto, quando è la risposta
  • Eh? Che cosa succede se si desidera solo per mettere un singolo carattere, perché è necessario aggiungere un NUL ad esso? L’ho fatto non per ottenere qualcosa in questa domanda?
  • la tua ipotesi è la risposta a questa domanda credo
  • Sì, mi piacerebbe avere con voto positivo di esso come una risposta come ho fatto io il commento haha.
  • Ci si va 🙂
  • %c si aspetta un dato di char tipo – un valore primitivo. %s si aspetta un dato di char * tipo, un puntatore. La differenza tra questi è enorme, in C, nonostante il fatto che entrambi applicare al testo.

 

11 Replies
  1. 98

    Probabilmente per distinguere tra di terminazione null stringa e un carattere. Se hanno appena avuto %s, poi ogni singolo personaggio deve essere di terminazione null.

    char c = 'a';

    Nel caso di cui sopra, c deve essere di terminazione null. Questa è la mia ipotesi, però 🙂

    • si può assumere all’interno di un commento, ma non in una risposta.. Ancora di +1 in quanto l’assunzione è corretta.. 😉
    • Non è una vera risposta, perché che potrebbe essere evitato %.1s
    • Quindi la tua soluzione potrebbe rendere il C funzionare solo con %s?
    • nel senso che se vuoi avere sempre il vostro char all’interno di un indirizzabile oggetto, sì.
    • Sì, questa è probabilmente la ragione Delphi funzione format non ha %c. Perché Pascal stringhe non sono di terminazione null.
    • Ipotesi può essere sbagliato 🙂
    • Un char è un singolo byte in memoria e mai terminata. La tua supposizione è sbagliata.
    • Non ho detto che. Probabilmente, la mia frase di formazione, potrebbe essere fonte di confusione. Come sapete, la stringa di formato per l’identificatore di formato %s deve essere null-terminated. Se non c’è %c nella lingua, quindi nel mio esempio di cui sopra, identificatore c deve essere null terminato per essere in grado di utilizzare con l’identificatore di formato %s.
    • Non so se implementazioni *printf può essere invocata a non leggere oltre il numero di byte che viene visualizzata. Concesso, se “%.1s” sono stati il modo in cui siamo perfettamente espresso “%c”, che sarebbe presto iniziare a farlo.
    • Confondere la risposta è peggio che dare una risposta sbagliata … io non posso credere che si stia discutendo di questo.
    • 1 questo è un povero risposta… Il motivo che printf("%s", c) non avrebbe funzionato, perché non è di terminazione null, ma perché printf si aspetta %s per puntare a una posizione di memoria, mentre c è un personaggio di valore. Di terminazione Null il motivo printf("%s", &c) non funzionerebbe, ma anche se lo facesse, avendo un %c identificatore sarebbe ancora ha senso, perché richiedono &c è coerente con il modo in cui ogni altra variabile, il tipo di stampa. Quindi basta dire “è a causa di terminazione null,” non è corretto.
    • Non vedo come 74 la gente ha pensato che questa fosse la risposta corretta in quanto non è detto che si debbano superare un char* per ottenere anche un solo carattere per la stampa con %s. Solo ripetendo quello che BlueRaja detto
    • ma allora deve c essere un char, ma c sarà nella maggior parte dei casi essere un int, e %c opere per char e int (a causa del tipo di promozione).
    • carattere non è di terminazione null. Stringa deve conoscere sia la dimensione O speciale, ‘null’ di carattere per consentire al sistema di conoscere la sua cessazione

  2. 73

    %s stampa caratteri fino a quando non raggiunge un 0 (o '\0', stessa cosa).

    Se solo un char x;, la stampa con printf("%s", &x);è necessario fornire l’indirizzo, poiché %s si aspetta un char* – vorresti ottenere risultati imprevisti, come &x + 1 potrebbe non essere 0.

    E quindi non solo la stampa di un singolo personaggio, a meno che non fosse null-terminated (molto inefficent).

    EDIT: Come altri hanno sottolineato, i due si aspettano cose diverse nel var args parametri un puntatore, l’altro è un singolo carattere. Ma che la differenza è un po ‘ chiaro.

    • si dovrebbe ricordare che %s prende un puntatore mentre %c assume un carattere stesso.
    • E la cosa più importante è solo in grado di stampare un carattere, se il suo indirizzo può essere preso. Che escluderebbero la stampa restituisce dalle funzioni, e.g, e anche registrare variabile.
    • Si potrebbe evitare il problema della terminazione null, fornendo un livello di precisione.
  3. 37

    Il problema menzionato da altri che un singolo carattere dovrebbe essere terminata null non è un vero e proprio uno. Questo potrebbe essere affrontato fornendo una precisione al formato %.1s sarebbe fare il trucco.

    Cosa più importante, a mio parere, è che per %s in una qualsiasi delle sue forme, è necessario fornire un puntatore ad uno o più caratteri. Che significa che non sarà in grado di stampare rvalues (espressioni calcolate la funzione restituisce ecc) o variabili registro.

    Edit: io sono veramente incazzato con la reazione a questa risposta, così ho probabilmente eliminare questo, questo non è davvero la pena. Sembra che le persone reagiscono in questo senza nemmeno aver letto la domanda o il saper apprezzare il tecnicismo della domanda.

    Di rendere chiaro: non dico che si dovrebbe preferire %.1s oltre %c. Io dico solo che i motivi per cui %c non può essere sostituito da diverse rispetto agli altri rispondere a fingere di raccontare. Queste le altre risposte sono solo tecnicamente sbagliato. Terminazione Null non è un problema con %s.

    • Si è vero… perché si preferisce avere %.1s oltre %c? Quello che stai facendo è re-inventare un marcatore per printf
    • No, non dico che qualcuno dovrebbe preferire che, in contrario. Io dico che %.1s avrebbe la funzionalità di stampa di un solo carattere che deve nemmeno essere null terminata, quindi la terminazione null non è una valida obiezione di “introdurre” %c.
    • +1 Per me questo è un punto molto importante, che parla di necessità piuttosto che convenienza @LuchianGrigore: perché si preferisce avere %.1s oltre %c? Perché non aggiungere un ulteriore descrittori di formato. Con precisione in formato descrittore è una funzionalità che deve essere fornito indipendentemente dal fatto che avete bisogno di per un singolo carattere. Così, alla fine, che permetterebbe di risparmiare un ulteriore specifica di formato.
    • Sarebbe %.1s essere in attesa di un char o un char*?
    • Che non era il vero motivo per essere discusso o dichiarato nella tua risposta quando l’ho visto.
    • Lo so, ma la mia domanda è questo risposta. Volete qualche marcatore che indica printf per stampare un singolo carattere. Si desidera passare char x; per la funzione. Quindi non c’è alcun vantaggio reale per uso %.1s oltre %c, perché utilizzando, ad esempio %.2s richiederebbe un diverso tipo di parametro.
    • nessuno dice che. La mia risposta si afferma semplicemente che la terminazione null non è il ragionamento, ma che prendendo l’indirizzo dell’oggetto è un argomento.
    • +1 corretto. Considerare printf("%c", 'a' + 8) – non è possibile scrivere che `printf(“%.1s”, ‘a’ + 8)`
    • -1 Questa risposta non il codice per la leggibilità primo.
    • hai letto la mia risposta. Trovo downvoting per davvero eccessivo. Non dico che nessuno dovrebbe usare %.1s per la stampa di un carattere. Non era questa la domanda. La domanda era se %c era strettamente necessario. E io dare una risposta affermativa a che, solo affermando che le ragioni sono diverse da quelli indicati nelle altre risposte.
    • per non leggere la risposta. Il quesito chiede Perché non X esiste in C, e questa risposta spiega chiaramente che X DEVE esistere per lavorare con rvalues. Senza considerazione per rvalues, la lingua/libreria designer, probabilmente (e come probabilmente DOVREBBE), hanno lasciato il %.1s come si fa la printf cleaner (e quindi più leggibile). Senza la c, la stampa del risultato di una funzione che restituisce un singolo carattere può essere abbastanza complesso (in particolare se di chiamare più funzioni con effetti collaterali e che sono dipendente).
    • La questione, per me, è stata generalmente “perché hanno questo?” Posso accettare la vostra lettura, tuttavia, in base alla chiusura po ‘ di “non rappresentazione in forma di stringa da solo essere sufficiente”, e dato il tuo edit io felicemente flip bit.
    • Basta essere curiosi qui: sarebbe printf(“%.1s”, &char) lavoro?
    • Se hai letto la mia risposta, vedrai che sì, lo fa.
    • Mendes e @Shanshui, strettamente parlando, la risposta è no, perché char è una parola chiave. 😉
    • Jens non rimuovere quella risposta. È l’unico interessante la risposta data. Il rvalue cosa è un grande affare, ma che può essere apprezzato solo con l’esperienza.

  4. 28

    La funzione printf è una funzione variadic, cioè un numero variabile di argomenti. Gli argomenti vengono inseriti nello stack prima della funzione (printf) è chiamato. In ordine per la funzione printf utilizzare lo stack, ha bisogno di sapere informazioni su ciò che è in pila, la stringa di formato è utilizzato per tale scopo.

    ad esempio

    printf( "%c", ch );    tells the function the argument 'ch' 
                           is to be interpreted as a character and sizeof(char)

    mentre

    printf( "%s", s );   tells the function the argument 's' is a pointer 
                         to a null terminated string sizeof(char*)

    non è possibile all’interno della funzione printf altrimenti determinare stack di contenuti ad esempio, di distinguere tra il ‘ch’ e ‘s’, perché in C non c’è nessun tipo di controllo durante la fase di runtime.

    • +1 per far sapere come funziona internamente.
    • ma sei completamente sbagliato con il vostro sizeof specifiche. Primo, ch viene promosso a un int (o su alcune piattaforme per un unsigned) e printf interpreta che int come carattere. Quindi la dimensione del parametro “in pila” è sizeof(int). Per il secondo hai sbagliato di nuovo, è sizeof(char*) e nient’altro. sizeof(int) può (e oggi spesso è) diverso. Terzo, non è necessario qualcosa di simile a una “pila” coinvolti. Come questi parametri vengono passati è a discrezione della piattaforma ABI , e tutto ciò che può accadere nei registri.
    • Jens è del tutto giusto. In realtà, si potrebbe anche cadere la parola “tecnicamente”, non è semplicemente giusto.
    • “Un po’ di imprecisione, a volte, consente di risparmiare un sacco di spiegazione” — Hector Hugh Munro
  5. 13

    %s dice di stampare tutti i caratteri fino a trovare un valore null (trattare la variabile come un puntatore).

    %c dice di stampare un solo carattere (trattare la variabile come un codice di carattere)

    Utilizzando %s per un personaggio che non funziona perché il personaggio sta per essere trattato come un puntatore, quindi prova a stampare tutti i caratteri che seguono il posto di memoria fino a quando non trova un null

    Rubare dalle altre risposte di spiegare in un modo diverso.

    Se si desidera stampare un carattere utilizzando %s, è possibile utilizzare le seguenti passare correttamente un indirizzo di un carattere e di mantenere la scrittura di messaggi sullo schermo fino a trovare un valore null.

    char c = 'c';
    printf('%.1s', &c);
    • Questo non è completamente vero. utilizzo di %s per un personaggio può fare tutto inaspettata da quando si interpreta un personaggio come un puntatore a un personaggio, che probabilmente punta a una posizione non valida.
    • Che è di destra, ho corretto
    • Giusto per essere chiari (dal momento che un sacco di gente confondere questi concetti), una stringa è terminata da null carattere, da non confondere con un null puntatore.
    • Solo per confondere la gente: carattere null '\0' e puntatore null sono rappresentati internamente come 0 🙂
    • No, possono essere rappresentati nel codice sorgente0. Le loro rappresentazioni interne possono essere molto diversa; un carattere null è tipicamente di 8 bit, mentre un puntatore null in genere è a 32 o 64 bit. Inoltre, un puntatore null rappresentazione interna è non necessariamente tutti i bit a zero (anche se è molto comunemente è).
    • La lingua in questione è C, e non ho mai sentito la rappresentazione interna di essere qualcosa di diverso da 0. Che è il motivo per cui si può utilizzare uno dei seguenti. if (pointer) o if (pointer != 0 ) o if(pointer != NULL ) Inoltre, penso 0s con 8, 16, 32 bit non sono molto diversi. bytes.com/topic/c/answers/213647-null-c
    • ISO standard C non dire o insinuare nulla sulla rappresentazione di un puntatore null. Un null puntatore costante, come una costante 0, esiste nel codice sorgente; quando viene utilizzato in un puntatore contesto, il compilatore traduce a qualunque rappresentazione interna è utilizzata per un puntatore null. Vedere anche la sezione 5 del comp.lang.c FAQ. È vero che più implementazioni di tutti i bit a zero, ma non è obbligatorio.
    • Il link che hai fornito, bytes.com/topic/c/answers/213647-null-c, ha diverse risposte che sono coerenti con quello che ho appena detto, che un puntatore null non necessariamente tutti i bit a zero (tra cui due che ho scritto io). Il contenuto sembra essere stato copiato senza attribuzione da comp.lang.c newsgroup Usenet.

  6. 7

    Per %s, abbiamo bisogno di fornire l’indirizzo della stringa, non il suo valore.

    Per %c, forniamo il valore dei caratteri.

    Se abbiamo usato il %s invece di %c, come possiamo fornire un '\0' dopo che i personaggi?

  7. 5

    Vorrei aggiungere un altro punto di prospettiva, questo divertente questione.

    Davvero tutto si riduce a questo tipizzazione dei dati. Ho visto le risposte qui che lo stato che si potrebbe fornire un puntatore a char, e di fornire un

    "%.1s"

    Questo potrebbe essere vero. Ma la risposta è la C di designer cercando di fornire la flessibilità per il programmatore, e in effetti un (seppur piccolo) in modo decrescente impronta della vostra applicazione.

    A volte, un programmatore potrebbe eseguire una serie di istruzioni if-else o un interruttore di caso, in cui il bisogno è semplicemente uscita di un personaggio basato su stato. Per questo, hard codifica i caratteri potrebbe infatti prendere meno spazio reale nella memoria come singoli caratteri di 8 bit contro il puntatore a 32 o a 64 bit (64 bit computer). Un puntatore occuperà più spazio in memoria.

    Se si desidera ridurre le dimensioni attraverso l’utilizzo effettivo di caratteri o puntatori a caratteri, quindi ci sono due modi si potrebbe pensare di fare questo all’interno di printf tipi di operatori. Sarebbe, per l’ .1s, ma come è la routine dovrebbe sapere per certo che siete veramente fornire un tipo di carattere contro un puntatore ad un char o il puntatore ad una stringa (array di caratteri)? Questo è il motivo per cui sono andato con “%c”, come è diverso.

    Divertimento Domanda 🙂

  8. 2

    C %c e %s specificatori di formato, perché gestire diversi tipi.

    Un char e una stringa sono diversi come la notte e 1.

    • Come si parla di %s e %c sono totalmente diverse, quindi pls dimmi perché il scanf(%s, &ch) e scanf(%c, &ch) dichiarazioni restituisce lo stesso risultato.Considerare ch è un char come char ch;
  9. 2

    %c si aspetta un char, che è un intero valore e di stampa in base alle regole di codifica.

    %s richiede un puntatore ad una locazione di memoria che contiene char valori, e stampa i caratteri in base alle regole di codifica fino a quando non trova un 0 (null) carattere.

    Quindi, come vedi, sotto il cofano, i due casi, mentre si somigliano non hanno molto in comune, come si lavora con i valori e l’altro con i puntatori. Uno è istruzioni per l’interpretazione di un valore integer specifico come un ascii char, e l’altro è l’iterazione il contenuto di una locazione di memoria char di char e di interpretarli fino a un valore pari a zero è stato rilevato.

  10. 2

    Ho fatto un esperimento con printf("%.1s", &c) e printf("%c", c).
    Ho usato il codice riportato di seguito per verificare, e il bash time utilità di avere runing tempo.

        #include<stdio.h>
        int main(){
            char c = 'a';
            int i;
            for(i = 0; i < 40000000; i++){
                //printf("%.1s", &c); get a result of 4.3s
                //printf("%c", c); get a result of 0.67s
            }
            return 0;
        }

    Il risultato dice che l’utilizzo di %c è 10 volte più veloce %.1s. Così, nonostante il fatto che %s può fare il lavoro di %c %c è ancora necessario per le prestazioni.

  11. 1

    Dal momento che nessuno ha fornito una risposta con QUALSIASI riferimento di sorta, qui è una printf specifica da pubs.opengroup.com, che è simile alla definizione del formato da IBM

    %c

    L’argomento di tipo int deve essere convertito in un unsigned char, e il byte risultante deve essere scritto.

    %s

    L’argomento deve essere un puntatore ad un array di char. Byte dell’array deve essere scritto (ma non inclusi) qualsiasi terminazione null byte. Se la precisione è specificata, non più di quel numero di byte deve essere scritto. Se la precisione non è specificato o è maggiore della dimensione della matrice, la domanda deve garantire che l’array contiene un byte null.

Lascia un commento