2012-02-27 2 views
1

Что-то я наткнулся и заставило меня задуматься. Почему это работает?Передача указателя в качестве аргумента функции в C

void foo (int* a) 
{ 
    int x = 3; 
    *a = x; 
} 

int main() 
{ 
    int a; 
    foo(&a); 
    return 0; 
} 

Но это приводит к ошибке сегментации (как на Visual Studio 2008 и НКУ)?

void foo (int* a) 
{ 
    int x = 3; 
    *a = x; 
} 

int main() 
{ 
    int* a; 
    foo(a); 
    return 0; 
} 

Это что-то определенное в языке или проблема с реализацией?

+0

Вы должны получить предупреждение со вторым примером. – Mysticial

ответ

4

При объявлении

int* a; 

Вы объявляете указатель переменной a, но вы не делаете это указывает ни на что. Тогда в функции, вы

*a = x; 

Какой разыменовывает указатель и пытается присвоить то, что он указывает на значение x. Но поскольку он не указывает ни на что, вы получаете неопределенное поведение, проявляющееся в ошибке сегментации.

Вы должны сделать это:

int i; // the actual integer variable 
int* a = &i; // a points to i 

Разница между этим и первый, что int a; объявляет реальную целочисленную переменную, то взять его адрес с &a и передает его функции. Указатель a внутри функции foo указывает на переменную a в main, и поэтому разыменование его и присвоение ему отлично.

+1

Также проблематично: 'printf ("% d \ n ", a);', поскольку ''% d "' ожидает тип 'int', а' a' - это тип 'int *'. –

+0

@ ChrisLutz получил его, спасибо. –

+0

Спасибо. Ошибка сегментации происходит даже без printf, поэтому я удалил ее из вопроса –

2
int a; 

Назначает память, как только вы ее объявляете, но это не так с int * a;

int *a; 

является объявлением указателя (MEMORY еще не выделена для этого).

int *a = (int*)malloc(sizeof(int)); // allocate memory