Указатель на C (должен быть простым) - PullRequest
2 голосов
/ 08 июня 2011

Я попробовал код, подобный этому:

int *a;
*a = 10;
printf("%d",*a);

в затмении, и он ничего не печатает.потому что я не дал начальное значение a?


Спасибо, это было полезно.Я знаю, что это проблематично. Я просто не был уверен, что именно проблема, например, если я сделаю printf("%d",a);, я вижу, что она содержит что-то, это правило С, что я должен дать ему место, на которое можно указать, тогда я могу начатьизменить значение в этом адресе?

Ответы [ 3 ]

15 голосов
/ 08 июня 2011
  • 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.
           */
10 голосов
/ 08 июня 2011

Вы не выделили память для.

Попробуйте

int *a;
a = (int*)malloc(sizeof(int)); //Allocating memory for one int.

*a = 10;
printf("%d", *a);
free(a); //Don't forget to free it.
1 голос
/ 08 июня 2011

Когда вы объявляете указатель, компилятор собирается только зарезервировать память для хранения переменной указателя. Если вы хотите, чтобы указатель указывал на что-то после факта, он должен быть чем-то, для чего выделена собственная память. Либо укажите на что-то, что было объявлено как int, либо выделите память из кучи для int.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...