int *a;
Определяет переменную, которая является указателем на целочисленный тип.Переменная типа указателя a
при создании содержит значение мусора. - Когда вы делаете
*a = 10;
, он связывается с использованием значения, хранящегося в a
, который является мусором, в качестве адреса и сохраняет значение 10
там.Поскольку мы не знаем, что содержит a
, и оно не выделено, поэтому a
указывает на какое-то место в памяти, которое неизвестно, и доступ к нему будет недопустимым, и вы получите ошибку сегментации (или что-то подобное). - То же самое в случае
printf ("%d", *a);
.Это также пытается получить доступ к значению, хранящемуся в некоторой неопределенной ячейке памяти, которую вы не выделили.
.
this variable is this is the location
stored in some with the address
address on the 'garbage'. You do not
stack have permissions to
access this
+-------+---------+
| name | value |
+-------+---------+ +---------+
| a | garbage |---->| ????? |
+-------+---------+ +---------+
После того, как вы определили переменную типа указателя, вам нужнозапросить некоторую ячейку памяти в операционной системе и использовать это значение ячейки памяти для сохранения в a
, а затем использовать эту ячейку памяти через a
.
Для этого вам необходимо выполнить следующее:
int *a;
a = malloc (sizeof (int)); /* allocates a block of memory
* of size of one integer
*/
*a = 10;
printf ("%d", *a);
free (a); /* You need to free it after you have used the memory
* location back to the OS yourself.
*/
В этом случае это похоже на:
После *a = 10;
.Переменная-указатель размещается в стеке.В этот момент a
содержит значение мусора.Затем a
указывает на адрес с таким значением мусора.
this variable is this is the location
stored in some with the address
address on the 'garbage'. You do not
stack have permissions to
access this
+-------+---------+
| name | value |
+-------+---------+ +---------+
| a | garbage |---->| ????? |
+-------+---------+ +---------+
После a = (int *) malloc (sizeof (int));
.Предположим, что malloc
возвращает вам некоторый адрес 0x1234abcd
, который будет использоваться.В этот момент a
будет содержать 0x1234abcd
, тогда a
будет указывать на действительное место в памяти, которое было выделено и зарезервировано для использования.Но обратите внимание, что значение внутри 0x1234abcd
может быть любым, т.е.мусор.Вы можете использовать calloc
, чтобы установить содержимое ячеек памяти, выделенных для 0
.
this variable is this is the location
stored in some 0x1234abcd , allocated
address on the by malloc, and reserved
stack for your program. You have
access to this location.
+-------+------------+
| name | value |
+-------+------------+ +---------+
| a | 0x1234abcd |---->| garbage|
+-------+------------+ +---------+
После *a = 10;
, с помощью *a
вы получите доступ к ячейке памяти 0x1234abcd
и сохраните 10
в него.
this variable is this is the location
stored in some 0x1234abcd , allocated
address on the by malloc, and reserved
stack for your program. You have
access to this location.
+-------+------------+
| name | value |
+-------+------------+ +---------+
| a | 0x1234abcd |---->| 10 |
+-------+------------+ +---------+
После free (a)
содержимое a
т.е.адрес памяти 0x1234abcd
будет освобожден, то есть возвращен обратно в операционную систему.Обратите внимание, что после освобождения 0x1234abcd
содержимое a
равно все еще 0x1234abcd
, но вы больше не можете получить к нему доступ легально, потому что вы только что освободили его.Доступ к содержимому, указанному по адресу, хранящемуся в a
, приведет к неопределенному поведению, наиболее вероятному из-за ошибки сегментации или повреждения кучи, так как он освобожден и у вас нет прав доступа.
this variable is this is the location
stored in some 0x1234abcd , allocated
address on the by malloc. You have freed it.
stack Now you CANNOT access it legally
+-------+------------+
| name | value |
+-------+------------+ +---------+
| a | 0x1234abcd | | 10 |
+-------+------------+ +---------+
the contents of a remains
the same.
EDIT1
Также обратите внимание на разницу между printf ("%d", a);
и printf ("%d", *a);
.Когда вы ссылаетесь на a
, он просто печатает содержимое a
, то есть 0x1234abcd
.И когда вы ссылаетесь на *a
, тогда он использует 0x1234abcd
в качестве адреса, а затем печатает содержимое адреса, в данном случае 10
.
this variable is this is the location
stored in some 0x1234abcd , allocated
address on the by malloc, and reserved
stack for your program. You have
access to this location.
+-------+------------+
| name | value |
+-------+------------+ +---------+
| a | 0x1234abcd |---->| 10 |
+-------+------------+ +---------+
^ ^
| |
| |
(contents of 'a') (contents of the )
| (location, pointed )
printf ("%d", a); ( by 'a' )
|
+----------------+
|
printf ("%d", *a);
EDIT2
Также обратите внимание, что malloc
может не дать вам какое-то действительное место в памяти.Вы всегда должны проверять, вернул ли malloc
правильное место в памяти.Если malloc
не может получить какую-то ячейку памяти для использования, он вернет вам NULL
, поэтому вам следует проверить, является ли возвращаемое значение NULL
или нет перед использованием.И, наконец, код становится:
int *a;
a = malloc (sizeof (int)); /* allocates a block of memory
* of size of one integer
*/
if (a == NULL)
{
printf ("\nCannot allocate memory. Terminating");
exit (1);
}
*a = 10;
printf ("%d", *a);
free (a); /* You need to free it after you have used the memory
* location back to the OS yourself.
*/