2010-03-29 18 views
15

Wczoraj w moim wywiadzie zadano mi to pytanie. (W tym czasie byłem pod wysokim ciśnieniem przez tak wiele nagłych pytań).Jaki jest problem z int * p; * p = 23;

int *p; 
*p=23; 
printf("%d",*p); 

Czy jest jakiś problem z tym kodem?

Wyjaśniłem mu, że próbujesz przypisać wartość do wskaźnika, któremu pamięć nie jest przydzielona.

Ale sposób, w jaki zareagował, był taki, jakbym się mylił. Chociaż dostałam tę pracę, ale potem powiedział, że Mohit znowu zastanawia się nad tym pytaniem. Nie wiem, co próbował powiedzieć. Proszę dać mi znać czy istnieje jakiś problem w mojej odpowiedzi?

EDIT dodałem kod na kartce; -

int *p; 
p=malloc(sizeof(int)); 
*p=23; 
printf("%d",*p);  

To musi być idealny kod ... mam rację ..

EDIT2

int *p; 
*p=23; 
OR 
int *p=23; 

Myślę, że oba mają problem. Ponieważ niektóre ciała mówią o tytule postu.

+4

Dobre pytanie. A ankieter ma rację, zadając takie pytania. Wyraźnie pokazują, co jest warte "pięć lat rozwoju C". – sharptooth

+4

Proszę zanotować swój tytuł pytania, a tekst pytania jest semantycznie inny. –

+0

Naprawiono tytuł do tego, co było (myślę) zamierzone – Yacoby

Odpowiedz

28

„próbuje przypisać wartość do wskaźnika do których pamięć nie została przydzielona”

Chyba tylko misphrased to nieco. Nie próbujesz przypisać wartości do wskaźnika, próbujesz ustawić wartość wskaźnika referand.

Ponieważ wskaźnik jest niezainicjowany, jest to, jak mówisz, niezdefiniowane zachowanie. Wskaźnik nie odwołuje się do niczego (przynajmniej nieważnie - jak wskazują inne odpowiedzi, bity pamięci o numerze p mogą zawierać wartość, która jest adresem pewnej lokalizacji w pamięci, a twój kod może je zastąpić. Standard zezwala na wszystko, co może się zdarzyć z UB, ale wiedząc coś o swojej implementacji, możesz często sprytnie zgadywać).

Prawdopodobnie w umyśle osoby przeprowadzającej wywiad masz dobry pomysł, ale warto mieć go dokładnie w głowie i w mowie, jaka jest różnica między palcem a księżycem, a także o tym, o czym mówisz .

+0

Wyjaśniłeś mu w odpowiedni sposób, że jego niezdefiniowane zachowanie powoduje, że wskaźnik nie ma żadnej pamięci i nie przydziela pamięci, aby przypisać wartość do niezainicjowanej pamięci. Chcę tylko potwierdzić, że logika była poprawna na .. Albo mój ans jest kompletnie błędny. –

+14

Nie, nie "przypisujesz wartości niezainicjowanej pamięci". Jeśli dam ci kopertę do dostarczenia, a adres (wartość wskaźnika) jest rozmazany (niezainicjowany), to nie możesz go dostarczyć. Nie próbujesz dostarczyć go do rozmytego * domu *, ale próbujesz ustalić, do którego domu odnosi się rozmazana * koperta *. Nie odnosi się to do żadnego domu, więc możesz wziąć resztę popołudnia (niezdefiniowane zachowanie). –

+3

Tak na przykład jeśli piszę 'char c; char * p = & c; * p = 'X'; ', następnie przypisuję wartość (" X ") do niezainicjowanej pamięci (zmienna' c'). Nic w tym złego. –

14

p nie został zainicjowany - przechowuje jakiś adres. Dereferencja to niezdefiniowane zachowanie.

Adres zapisany w p może zostać odwzorowany w przestrzeni adresowej procesu lub może nie zostać zamapowany. Jeśli jest on mapowany, niektóre niepowiązane (ale być może ważne dla programu) dane są przechowywane pod tym adresem. Tak więc albo program zawiesza się natychmiast z powodu ochrony pamięci, albo zmieniasz dane należące do tego programu. Konsekwencje tego ostatniego mogą się różnić - być może nic się nie dzieje, może nie zauważysz, może zepsujesz ważne dane i program się rozpadnie - klasyczne niezdefiniowane zachowanie.

7

"p" wskazuje na nieznane miejsce, a nie na pamięć "nie przydzielono".

Różnica polega na tym, że ponieważ jest to niezdefiniowane, może to wskazywać na przydzielonej pamięci, nawet jeśli ta pamięć nie miało być dostępne przez tę funkcję.

2

int * p;

initailly powyższy wskaźnik zawiera jakąś wartość śmieci (nieprawidłowy adres lub wartość un przydzielono adres).

* p = 23;

wówczas starają się umieścić pewną wartość (23) w nieprawidłowej pamięci prowadzi do nieokreślonego zachowania.

3
#include <stdio.h> 
#include <stdlib.h> 

int main(char** argv) { 
    // THIS POINTER IS NOT DECLARED (SO IT'S NOT USABLE/INVALID) 
    int *p; 
    // 1) SO RESERVE MEMORY AND SET POINTER TO VALID MEMORY... 
    p=malloc(sizeof(int)); 
    // 2) ...CHECK IF ALLOCATION WAS OK... 
    if (p) { 
    *p=23; 
    printf("%d",*p); 
    } else printf("sorry, no memory"); 
    // 3) ...AND FINALLY DE-ALLOCATE MEMORY (FREEING IS IGNORED WHEN p IS NULL)! 
    free(p); 
} 
+1

Sprawdź wartość zwracaną przez 'malloc' dla wartości null. –

+1

Myślę, że * p = 23; powinno nastąpić po przeprowadzeniu kontroli przydziału. – Brian

+0

Nie wywoływaj 'free()', chyba że 'malloc()' również się powiodło. To wywołanie powinno następować bezpośrednio po 'printf()' wewnątrz 'if'. –

0

Pomijając fakt, że przykład nie przydzielić pamięci dla wartości 23, to też nie będzie kompilować w pierwszej kolejności, ponieważ masz dwie postacie w swojej characted stałej (które ma na celu być struną). Np. Zamień "% d" na "% d" w instrukcji printf.

+0

@Jasper Bekkers Yupp. –

3

int * p = 23;

To jest zupełnie inna. Tutaj deklarujesz wskaźnik i przypisujesz mu wartość 23. Oznacza to, że teraz wskazuje na lokalizację pamięci 23, która może ale nie musi zawierać czytelnych danych.

Ale po prostu przypisując dowolną wartość wskaźnika bez dereferencji to jest całkowicie bezpieczne.

Powiązane problemy