Mi történik mikor két változót egyenlővé teszek C-ben?
Írtam egy szám beolvasást ami mindaddig működik amíg nem dolgozok a c változóval, amibe beolvastam az inputot. Nem tudok rájönni miért van így. A választ előre is köszönöm
#include <stdio.h>
#include <stdlib.h>
int main()
{
int m;
int n,c;
m = getchar();
while (m != '\n') {
if ((m >= 48) && (m <= 57)) {
n = m - 48;
} else {return 0;}
c = c*10+n;
m = getchar();
}
printf("%d\n",c);
int i;
i = c;/*ha az értékadást kiveszem jó*/
printf("%d\n",i);
return 0;
}
Hát, most erre mit mondjak? Itt a programod futtatása az én linuxos gépemen:
123
123
123
Amint látod, semmi sem bukott ki, pedig a kódodon egy mikurkát sem változtattam. Csak feltételezem, hogy az inicializálatlan c változóban nálam véletlenül 0 volt (esetleg a fordítóm nullázta létrehozáskor), nálad meg nem.
Lefordítottam a programodat a windowsos gépemen is. Ott ezt kaptam:
123
60123
60123
Tehát nem egyezik meg a linuxos változattal sem, meg a tieddel sem -- ami erősen arra utal, hogy a fentebb elmondottaknak megfelelően véletlenszerű memóriaszemétről van szó. De az sem igaz, hogy az i = c; értékadás rontana el bármit. Ha kiveszek minden i-vel kapcsolatos dolgot, akkor printf("%d\n", c); után a te elmondásod szerint ennek kéne a képernyőn lennie:
123
123
Nálam pedig ez van:
123
60123
Vagyis a memóriaszemét ugyanúgy megbosszulja magát, akár van, akár nincs i = c; -- ha nálad szerencsésebben ütött ki, azt csak a vakvéletlennek köszönd.
Ha viszont c értékét 0-ra inicializálom, akkor bizony (i-vel vagy anélkül) a helyes értéket írja ki.
"az üres értékű változóba helyesen beleíródik a beolvasott szám"
A c változóba semmi értelmes nem kerül !!!!!
Másold ki ide légyszi azt a sort, amiben a c egy konkrét értéket kap. (Nem, nem a "c=c*10+n".)
Olyan, mintha azt kérdeznék tőled, mennyi x+2? Erre te azt mondod, hogy jó, de mennyi az x? Jobb híján a hasadra ütsz, és beírsz x-be egy akármilyen számot, kiszámolod, a kérdező meg örül, mert kapott egy eredményt. Te és a progid is pont ezt csináljátok a c változóval.
Köszi tabaki ! Szóval úgy látszik fordító függő ami történik és talán nem ezen a szinten kéne megérteni. Akik még nem vágtág le min rugózom azoknak leírom :
#include <stdio.h>
#include <stdlib.h>
int main()
{
int m;
int n,c;
m = getchar();
while (m != '\n') {
if ((m >= 48) && (m <= 57)) {
n = m - 48;
} else {return 0;}
c = c*10+n;
m = getchar();
}
printf("%d\n",c);
}
Nekem ez a kód ha hiszintek ha nem linux alatt gcc compilerrel tökéletesen lefut, igen azok ellenére, hogy a c-nek nem adtam értéket.
567
567
Ha tényleg ennyire érdekel a fordítók és a natív kód világa, akkor kezd egy olyan progival, ami a problémát célozza meg.
Pl:
int main()
{
int c;
printf("%d\n",c);
c += 1;
printf("%d\n",c);
c = 1;
printf("%d\n",c);
}
Fordítsd le csak asm kódig, és vizsgáld meg, milyen szekvencia hajtódik végre különböző fordítók esetén.
.file "main.c"
.section .rodata
.LC0:
.string "%d\n"
.text
.globl main
.type main, @function
main:
.LFB2:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $16, %rsp
call getchar
movl %eax, -12(%rbp)
jmp .L2
.L5:
cmpl $47, -12(%rbp)
jle .L3
cmpl $57, -12(%rbp)
jg .L3
movl -12(%rbp), %eax
subl $48, %eax
movl %eax, -4(%rbp)
movl -8(%rbp), %edx
movl %edx, %eax
sall $2, %eax
addl %edx, %eax
addl %eax, %eax
movl %eax, %edx
movl -4(%rbp), %eax
addl %edx, %eax
movl %eax, -8(%rbp)
call getchar
movl %eax, -12(%rbp)
jmp .L2
.L3:
movl $0, %eax
jmp .L4
.L2:
cmpl $10, -12(%rbp)
jne .L5
movl -8(%rbp), %eax
movl %eax, %esi
movl $.LC0, %edi
movl $0, %eax
call printf
movl $0, %eax
.L4:
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE2:
.size main, .-main
.ident "GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.6) 5.4.0 20160609"
.section .note.GNU-stack,"",@progbits
Direkt szívatsz minket ezzel a szörnyű (és még mindig hibás) kóddal?
A deklarációk, ez négy int méret, ebből három a lokális változók.
(Ahogy korábban írtam, csak belerúg a stack pointerbe.)
subq $16, %rsp
A változóidat így találod meg:
-12(%rbp) -> m
-8(%rbp) -> c
-4(%rbp) -> n
Itt nyúl először a c-hez:
movl -8(%rbp), %edx
Számolgat vele, és itt írja vissza:
movl %eax, -8(%rbp)
Vagyis pont az történik, amit előttem már leírtak páran.
Kapcsolódó kérdések:
Minden jog fenntartva © 2025, www.gyakorikerdesek.hu
GYIK | Szabályzat | Jogi nyilatkozat | Adatvédelem | Cookie beállítások | WebMinute Kft. | Facebook | Kapcsolat: info(kukac)gyakorikerdesek.hu
Ha kifogással szeretne élni valamely tartalommal kapcsolatban, kérjük jelezze e-mailes elérhetőségünkön!