Imprimarea unui caracter cu printf (Programare, C++, C, Printf, Sizeof)

user535450 a intrebat.

Ambele coduri sunt aceleași

char ch = 'a';
printf("%d", ch);

Se va imprima o valoare de gunoi?

Sunt confuz în legătură cu acest lucru

printf("%d", ''); 

Va imprima 0 sau o valoare de gunoi?Pentru că atunci când fac acest lucru

printf("%d", sizeof('
')); 

Se imprimă 4. De ce este sizeof('
')
4 octeți?Același lucru în C++ imprimă 1 octet. De ce se întâmplă asta?

Deci, aici este întrebarea principală

în limbajul c este printf("%d", '') ar trebui să tipărească 0

iar în C++ printf("%d", '') ar trebui să se tipărească gunoi?

6 răspunsuri
peoro

%d imprimă un număr întreg: va imprima reprezentarea ascii a caracterului tău. Ceea ce aveți nevoie este %c:

printf("%c", ch);

printf("%d", ''); tipărește reprezentarea ascii a '', care este 0 (prin scăparea lui 0, îi spuneți compilatorului să folosească valoarea ascii 0.

printf("%d", sizeof('
'));
tipărește 4, deoarece un literal de caracter este un int, în C, și nu un char.

Comentarii

  • @nightcracker: hm? Dacă printf("%d", ch); „tipărește o valoare de gunoi”, cred că este pentru că a vrut să tipărească A, în loc de valoarea sa ascii… –  > Por peoro.
  • Nu a spus niciodată că ceva imprimă o valoare de gunoi, a întrebat dacă o va face sau nu. –  > Por orlp.
  • @nightcracker: hum, care e diferența? Nu înțeleg ce vrei să spui. –  > Por peoro.
  • Pur și simplu, răspunsul tău nu este un răspuns la întrebarea lui OP. El era pur și simplu curios de rezultatele %d tipărirea caracterelor, %c nu are nicio legătură. –  > Por orlp.
  • De fapt, asta este exact ceea ce căutam (am ajuns aici prin motorul de căutare). Chiar dacă nu răspunde la întrebarea inițială a lui OP, îi va ajuta pe alții -.  > Por bobroxsox.
scoffey

Acest lucru ar trebui să tipărească valoarea ASCII a caracterului, ca %d este secvența de evadare pentru un număr întreg. Deci, valoarea dată ca argument al printf este luată ca număr întreg atunci când este tipărită.

char ch = 'a';
printf("%d", ch);

Același lucru este valabil și pentru printf("%d", '');, unde caracterul NULL este interpretat ca fiind un număr întreg 0.

În cele din urmă, sizeof('
')
este 4, deoarece în C, această notație pentru caractere reprezintă numărul întreg ASCII corespunzător. Astfel, „
” este același lucru cu 10 ca număr întreg.

Totul depinde de interpretarea pe care o dați octeților.

Comentarii

  • +1 astfel încât printf(„%d”, ch) va produce (int) 97 și printf(„%d”, ‘’) (int) 0 –  > Por BlackBear.
  • Aș spune asta ca „Deci ‘
    ‘ este un int, 32 de biți, 4 octeți, iar sizeof() returnează 4. valoare a lui ‘
    ‘ este 10, zecimal. NEWLINE în ascii.” Propoziția originală, unică, este adevărată, dar poate prea laconică. –  > Por Bill IV.
John Bode

În C, expresiile constante de caractere, cum ar fi '
'
sau 'a' au tipul int (deci sizeof '
' == sizeof (int)
), în timp ce în C++ acestea au tipul char.

Instrucțiunea printf("%d", ''); ar trebui să tipărească pur și simplu 0; tipul expresiei '' este int, iar valoarea sa este 0.

Instrucțiunea printf("%d", ch); ar trebui să tipărească codificarea numerelor întregi pentru valoarea din ch (pentru ASCII, 'a' == 97).

orlp

În C char este promovat la int în expresii. Asta explică cam toate întrebările, dacă vă gândiți bine.

Sursa: Limbajul de programare C de Brian W.Kernighan și Dennis M.Ritchie

O lectură obligatorie dacă doriți să învățați C.

Vedeți și această pagină de pe stack overflow, unde oameni mult mai experimentați decât mine pot explica mult mai bine decât voi putea eu vreodată.

Comentarii

  • @BlackBear: Da, pentru că (pe majoritatea sistemelor) un char este un octet și un int patru, deci este o promovare. –  > Por orlp.
  • Citez literal cartea, ei folosesc cuvântul promovare. Este același lucru cu un int cast (cred). –  > Por orlp.
  • Îți dau +1 pentru link. Cuvântul promotion încă mă încurcă totuși, dar cred că ești clar ;). – user418748
  • Termenul „promovare” este folosit și în standardul limbajului C, secțiunea 6.3.1.1. –  > Por John Bode.
  • Explicația privind promovarea nu este foarte precisă. sizeof('a') este 4 dar sizeof(ch) este 1 dacă ch este un char. În C, expresia 'a' este aceeași cu (int) 97. Nu există nicio promovare. Cu toate acestea, în C++, expresia respectivă are tipul char. –  > Por scoffey.
spinooosa
#include <stdio.h>
#include <stdlib.h>

int func(char a, char b, char c) /* demonstration that char on stack is promoted to int !!!
                                    note: this promotion is NOT integer promotion, but promotion during handling of the stack. don't confuse the two */
{
  const char *p = &a;
  printf("a=%d
"
         "b=%d
"
         "c=%d
", *p, p[-(int)sizeof(int)], p[-(int)sizeof(int) * 2]); // don't do this. might probably work on x86 with gcc (but again: don't do this)
}


int main(void)
{
  func(1, 2, 3);

  //printf with %d treats its argument as int (argument must be int or smaller -> works because of conversion to int when on stack -- see demo above)
  printf("%d, %d, %d
", (long long) 1, 2, 3); // don't do this! Argument must be int or smaller type (like char... which is converted to int when on the stack -- see above)



  // backslash followed by number is a oct VALUE
  printf("%d
", '377');             /* prints -1   -> IF char is signed char: char literal has all bits set and is thus value -1.
                                                     -> char literal is then integer promoted to int. (this promotion has nothing to do with the stack. don't confuse the two!!!) */
                                      /* prints 255  -> IF char is unsigned char: char literal has all bits set and is thus value 255.
                                                     -> char literal is then integer promoted to int */


  // backslash followed by x is a hex VALUE
  printf("%d
", 'xff');             /* prints -1   -> IF char is signed char: char literal has all bits set and is thus value -1.
                                                     -> char literal is then integer promoted to int */
                                      /* prints 255  -> IF char is unsigned char: char literal has all bits set and is thus value 255.
                                                     -> char literal is then integer promoted to int */


  printf("%d
", 255);                // prints 255


  printf("%d
", (char)255);          // prints -1   -> 255 is cast to char where it is -1
  printf("%d
", '
');               // prints 10   -> Ascii newline has VALUE 10. The char 10 is integer promoted to int 10
  printf("%d
", sizeof('
'));       // prints 4    -> Ascii newline is char, but integer promoted to int. And sizeof(int) is 4 (on many architectures)
  printf("%d
", sizeof((char)'
')); // prints 1    -> Switch off integer promotion via cast!

  return 0;
}

Comentarii

  • Vă rugăm să vă limitați rândurile la 90 de caractere. Jumătate din textul dvs. este ascuns. –  > Por A.L.
  • @A.L Dă vina pe ecranele alea nebunești de înaltă rezoluție 16:9! Cu un raport de aspect 4:3, prietenos pentru programatori, nimeni nu ar mai scrie vreodată linii atât de lungi și nebunești 😉 –  > Por BitTickler.
davep

Da, se tipărește GARBAGE dacă nu ești norocos.

FOARTE IMPORTANT.

Tipul argumentului printf/sprintf/fprintf TREBUIE să se potrivească cu tipul de format asociat char.

Dacă tipurile nu se potrivesc și se compilează, rezultatele sunt foarte nedefinite.

Multe compilatoare mai noi știu despre printf și emit avertismente în cazul în care tipurile nu se potrivesc. Dacă primiți aceste avertismente, corectați-le.

Dacă doriți să convertiți tipurile pentru argumentele funcțiilor variabile, trebuie să furnizați cast-ul (adică o conversie explicită), deoarece compilatorul nu își poate da seama că trebuie efectuată o conversie (așa cum poate face în cazul unui prototip de funcție cu argumente tipizate).

printf("%d
", (int) ch)

În acest exemplu, lui printf i se spune că există un „int” pe stivă. Cast-ul se asigură că, indiferent ce returnează sizeof (un fel de întreg lung, de obicei), printf va primi un int.

printf("%d", (int) sizeof('
'))

Comentarii

  • -1 Aproape totul este greșit aici. Presupunând că prototipul pentru printf este vizibil, este perfect în regulă să se treacă un char sau un short la %d datorită promovării integrale care se întâmplă pentru funcțiile variadice. Castingul este cel mult o prostie. –  > Por Jens.