Char till int och vice versa verkar fungera, hur?

C, C++, Pascal, Assembly, Raspberry, Java, Matlab, Python, BASIC, SQL, PHP, etc.
Användarvisningsbild
Henry
Inlägg: 23619
Blev medlem: 20 april 2005, 02:52:47
Ort: Lund

Char till int och vice versa verkar fungera, hur?

Inlägg av Henry »

Hur kan följande kod fungera?

Jag tar ett tecken i en char array och sätter i en vanlig int och sedan skriver jag innehållet i int:en till ett annat ställe i arrayn vilket verka funka då det visas på displayen att något sådant har skett. Det skall ju inte funka, som jag ser det, men ser ju så ut att ändå hur?

Kod: Markera allt

#include <LiquidCrystal.h>

LiquidCrystal lcd(40, 42, 28, 26, 24, 22);

int up_down = 0;

char value[] = "1.23E-4";

void setup() {

  lcd.begin(20, 4);
  lcd.clear();
  //delay(1000);


  up_down = value[0];
  value[2] = up_down;
  value[3] = up_down;
  value[6] = up_down;
  lcd.print(value);

  //Och får 1.11E-1 som "väntat" men hur och kompilatorn borde väl klaga, vilket den inte gör?

}

void loop() {

}

Shimonu
Inlägg: 295
Blev medlem: 21 oktober 2015, 22:44:33

Re: Char till int och vice versa verkar fungera, hur?

Inlägg av Shimonu »

I värsta fall skulle det vara en varning att du implicit konverterar en int till char.

Men jag skulle tro kompilatorn är så smart att den ser att du aldrig använder int:en mer än att skriva till char-arrayen och då kan int:en skippas helt. Så den skriver value[0] direkt till array-platserna.

Inget konstigt
johano
Inlägg: 1943
Blev medlem: 22 januari 2008, 10:07:45
Ort: Stockholm

Re: Char till int och vice versa verkar fungera, hur?

Inlägg av johano »

Det sker en massa implicit konvertering av integer datatyper också:
Följande är helt ok:

Kod: Markera allt

char c1 = '0';
int i = c1;
char c2 = i;
bearing
Inlägg: 11253
Blev medlem: 2 mars 2006, 01:01:45
Ort: Ängelholm

Re: Char till int och vice versa verkar fungera, hur?

Inlägg av bearing »

När man kompilerar i Arduino-miljön är många varningar inte påslagna i kompilatorn. Men du kan ju gå in i inställningarna och aktivera inställningen så att du ser texten från kompilering och länkning, och kika där ifall den visar någon varning.

Sen är det så att avr-gcc optimerar koden väldigt hårt, och gör en del specialare för att snabba upp koden på en 8-bitare.

Ifall du skriver en 16-bit variabel till en plats i en 8-bit array kommer inte två värden i arrayen ändras. Utan 16-bit-värdet kommer först trunkeras till 8-bit, vilket innebär att de 8 övre bitarna slängs. Sedan skrivs de 8 nedre bitarna till angiven plats i 8-bit arrayen. I ditt fall är de övre 8 bitarna av din 16-bit int alltid noll, så trunkeringen har inte någon betydelse.
Senast redigerad av bearing 2 oktober 2019, 00:32:52, redigerad totalt 1 gång.
Användarvisningsbild
Henry
Inlägg: 23619
Blev medlem: 20 april 2005, 02:52:47
Ort: Lund

Re: Char till int och vice versa verkar fungera, hur?

Inlägg av Henry »

Hade visst redan satt den på compiler warnings = all, men den visar nada om detta vilket faktiskt förvånar mig lite.

Hade dock mina misstankar om vad som försiggår här och kollade det precis genom att skriva ut innehållet i up_down och visst char görs om till siffror enligt ascii tabellen och vid överföring till arrayn omvandlas det till char igen, det trodde jag då inte och då blir det en ordentlig ändring i resten av koden.
bearing
Inlägg: 11253
Blev medlem: 2 mars 2006, 01:01:45
Ort: Ängelholm

Re: Char till int och vice versa verkar fungera, hur?

Inlägg av bearing »

Nej, det sker inte någon omvandling från / till ascii när du skriver typer till varandra. Det där med tecken och dess ascii-nummer har ingen betydelse / är samma sak i C/C++. Men print-funktionen är skriver så att den gör skillnad, och skriver ut ascii-numret i ena fallet, och själva tecknet i andra fallet.
Användarvisningsbild
Henry
Inlägg: 23619
Blev medlem: 20 april 2005, 02:52:47
Ort: Lund

Re: Char till int och vice versa verkar fungera, hur?

Inlägg av Henry »

Suck, varför skall det inte vara enkelt. :doubt:

Men ok, om jag då har en int som jag kan räkna upp och ned 0 - 9 med så kan jag då bara sätta den till att skriva till tex array[1] och om jag sedan skriver ut arrayn genom serial.print så skickas det som finns i arrayn i klartext?
Användarvisningsbild
sodjan
EF Sponsor
Inlägg: 43178
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping
Kontakt:

Re: Char till int och vice versa verkar fungera, hur?

Inlägg av sodjan »

Njae... En "char" är i princip en 8-bit int. Så det är ingen "konvertering"
mellan två helt olika data typer, det är bara en tilldelning mellan en 8-bit
och en 16-bit integer. I en riktningen ("neråt") trunkering av de högsta
8 bitarna och i det andra fallet ("uppåt") så läggs de 8 högsta biterna
till som nollor.

Det hade naturligtvis varit mer logiskt om C faktiskt hade haft en riktig
8-bit integer från början (kallad t.ex "byte"), och en char som enbart
är för texthantering. Samt att det inte skulle gå att tilldela mellan dom
direkt utan att göra en explicit cast för att visa att man vet vad man
håller på med...

Och allt detta har inte ett smack med ASCII att göra, det är enbart ett
sätt att representera vissa 8-bitars integers med tecken ur ett alfabet.

> Men ok, om jag då har en int som jag kan räkna upp och ned 0 - 9...

Jag antar att du menar x'00' till x'09'?

> med så kan jag då bara sätta den till att skriva till tex array[1]...

Ja visst.

> ...och om jag sedan skriver ut arrayn genom serial.print så skickas
> det som finns i arrayn i klartext?

Om serial.print gör en konvertering av det binära värdet till motsvarande
ASCII tecken, så får du '0' till '9', alltså x'30' till x'39'.

Annars får du så klart de 10 första kontrolltecknen i ASCII tabellen...
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
bearing
Inlägg: 11253
Blev medlem: 2 mars 2006, 01:01:45
Ort: Ängelholm

Re: Char till int och vice versa verkar fungera, hur?

Inlägg av bearing »

Vet inte hur jag ska förklara, men en dator kan ju bara spara bitar.
char c = 'A'; innebär att 0x41, eller 65, sparas i c.
char d = 0x41; innebär att 0x41, eller 65, sparas i d.
int mitt_heltal = 'A'; innebär att 0x0041, eller 65, sparas i mitt_heltal .

serial.print() är skriven i C++, vilket innebär att funktionen förstår vilken typ av argument den får. (Enkelt uttryckt.)

I fallet serial.print(c) skickas 0x41 till serieporten, eftersom att c är av typen char, som ska levereras oförändrat. Som tas emot av PCn, där ditt terminalprogram slår upp 0x41 i ascii-tabellen och visar därför den grafiska symbolen A i fönstret.
Exakt samma händer i fallet serial.print(d). 0x41 skickas till serieporten. Sen slår ditt terminalprogram upp 0x41 i ascii-tabellen och visar därför ett A.

I fallet serial.print(mitt_heltal) gör print-funktionen något annat. Funktionen är programmerad att istället för att skicka det råa värdet 0x0041 göra en hex-decimal-omvandling av integern, och sedan skicka resultatet, siffra för siffra, samt omvandlat till ascii, på serieporten. Funktionen gör därför en beräkning motsvarande att dividera mitt_heltal med 10 i en loop, och skickar sedan resultaten av dessa beräkningar som ascii på serieporten. Att omvandla från en siffra 0-9 till ascii för '0' (0x30) - '9' (0x39) är enkelt, eftersom att de ligger i följd i ascii-tabellen. Genom att addera '0' till den aktella siffran, fås därför ascii-koden för siffran, alltså ett tal mellan 0x30 och 0x39, eller 48 - 57. serial.print(mitt_heltal) kommer alltså skicka en eller flera chars innehållande nummer inom intervallet 48-57. Som ditt terminalprogam sedan, för var var och en av dessa, slår upp i ascii-tabellen, och sedan visar grafiska symboler.

Hoppas att jag inte rörde till det för dig! =)
Senast redigerad av bearing 2 oktober 2019, 01:28:57, redigerad totalt 1 gång.
Användarvisningsbild
sodjan
EF Sponsor
Inlägg: 43178
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping
Kontakt:

Re: Char till int och vice versa verkar fungera, hur?

Inlägg av sodjan »

Kan du inte ta med lite UTF8 också och förklara hur ett tecken "på skärmen"
kan bli en, två, tre eller fyra bytes i filen... :-)

Det tog mig flera veckor att förklara för våra programmerare från HCL vad
skillnaden var mellan det hexadecimala uttrycket "9E" och värdet x'9E'.
Det var tydligen jättesvårt att skilja på det som är lagrat och på alla
olika sätt att representera det lagrade i programkod...
bearing
Inlägg: 11253
Blev medlem: 2 mars 2006, 01:01:45
Ort: Ängelholm

Re: Char till int och vice versa verkar fungera, hur?

Inlägg av bearing »

Jag överlåter den biten åt mer nattaktiva forumister =)
Palle500
Inlägg: 4494
Blev medlem: 6 juni 2015, 14:53:06

Re: Char till int och vice versa verkar fungera, hur?

Inlägg av Palle500 »

Sen kanske vi skall nämna att char per definition endast har 7 signifikanta bitar. Så för att vara säker när man använder char som 8 bits blnärer skall man definiera som unsigned char :-)
Användarvisningsbild
Henry
Inlägg: 23619
Blev medlem: 20 april 2005, 02:52:47
Ort: Lund

Re: Char till int och vice versa verkar fungera, hur?

Inlägg av Henry »

Tack för det, det visste jag inte.

sodjan: intressant info, tackar. :)

Bearing, nejdå jag hänger med, jäkla komplext för att skicka lite tecken. :D Hoppas bara sensorn som det skall skickas till sedan emulerar det den skall så jag får tillbaka det jag vill men har en uppfattning att så kommer att ske.

Var en del grejer här som jag inte visste om, kul och intressant och läsa, tack boys. :)
Användarvisningsbild
Icecap
Inlägg: 26147
Blev medlem: 10 januari 2005, 14:52:15
Ort: Aabenraa, Danmark

Re: Char till int och vice versa verkar fungera, hur?

Inlägg av Icecap »

int som variabeltyp är besvärlig.

C-definitionen är att int är en typ som µC'n "naturligt" kommer åt med minimalt antal läsningar.

Alltså: i en 8-bitars µC är det en byte (fast då signed), i en 32-bitars µC är det (nästan alltid) en signed long.

Så 'int' bör man undvika att använda till annat än värden som är sanna (≠ 0) eller falska (= 0) helt enkelt - eller iaf. inte överstiger ±127.

Man kan såklart välja att definera som 'unsigned int' vilket gör att värdet 100% säkert hanterar värden mellan 0 och 255 men annars har de samma problem.

Ska man alltså göra portable funktioner ska man använda de nyare definitioner (t.ex. int8_t, uint8_t, int16_t, uint16_t osv.) där man säkerställer att variablerna får minst rätt storlek. Dessa definitioner finns med från c99 och C++11.
Användarvisningsbild
sodjan
EF Sponsor
Inlägg: 43178
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping
Kontakt:

Re: Char till int och vice versa verkar fungera, hur?

Inlägg av sodjan »

OK, ja det är ju klart...

*Jag* använda begreppet "int" för att symbolisera en heltals
variabel som man kan "räkna med", helt oavsett storlek eller
signed/unsigned, det är bara varianter på samma tema.

Det var inte min mening att man specifikt ska använda just "int"...

Det idiotiska i C (med en massa annat annat) är att man kallade
en 8-bitars int för "char" (och inte har någon specific "text" typ).
Skriv svar