Оператор разыменования (*) различия между char * и int * - PullRequest
5 голосов
/ 19 апреля 2020

Почему оператор (*) необходим для доступа к значению переменной int*, но не для char*?

char *char_ptr; 
int *int_ptr;
int mem_size = 50;

char_ptr = (char *) malloc(mem_size);
strcpy(char_ptr, "This is memory is located on the heap.");
printf("char_ptr (%p) --> '%s'\n", char_ptr, char_ptr);


int_ptr = (int *) malloc(12);
*int_ptr = 31337; 
printf("int_ptr (%p) --> %d\n", int_ptr, *int_ptr);

Выход:

char_ptr (0x8742008) --> 'This is memory is located on the heap.' 
int_ptr (0x8742040) --> 31337

Ответы [ 4 ]

7 голосов
/ 19 апреля 2020

Это связано с тем, как работают спецификаторы формата printf: формат %s ожидает для своего соответствующего аргумента указатель на символ (точнее, адрес * 1005). * -определенный строка - который может быть массивом char, выделенным буфером с хотя бы одним нулевым байтом или строковым литералом ), поэтому вы можете просто присвоить ей переменную char_ptr как есть; с другой стороны, формат %d ожидает целое число (не указатель на целое число), поэтому необходимо разыменовать переменную int_ptr с помощью оператора *.

Примечание о хорошем стиле программирования: Как уже упоминалось в комментариях к вашему вопросу, обязательно вызовите free() в какой-то момент для каждого буфера, выделенного с malloc, или вы введете утечки памяти в ваш код. Также см .: Я разыгрываю результат mallo c? .

0 голосов
/ 19 апреля 2020

"Почему оператор (*) необходим для доступа к значению переменной int*, а не для char*?"

Поскольку в функции printf() спецификатор формата %s ожидает соответствующий аргумент типа char * - указатель на строку, в то время как %d ожидает аргумент типа int.

В последнем случае оператор разыменования * требуется для разыменования int_ptr и для получения значения int объекта int_ptr указывает на

As char_ptr уже относится к типу char* в соответствии с требованиями %s, нет необходимости разыменовывать его.


Примечания:

1.

int_ptr = (int *) malloc(12);

Обратите внимание, что с 12 байтами в большинстве современных систем вы сможете выделить только 1 int объект, так как для этого требуется 8 байт. Оставшихся 4 байтов недостаточно для хранения другого.

Если вы хотите выделить место только для одного int, используйте sizeof(*int_ptr):

int_ptr = (*int) malloc(sizeof(*int_ptr));

2.

Также не забудьте free() хранилище, выделенное malloc() после его использования:

free(int_ptr);
free(char_ptr);

3.

Кроме того, нет необходимости разыгрывать возврат значение malloc(): ли я приведу результат mallo c?

char_ptr = malloc(mem_size);
int_ptr = malloc(sizeof(*int_ptr));
0 голосов
/ 19 апреля 2020

Для любого указателя или массива p и индекса i выражение p[i] точно равно *(p + i). Из этого следует, что *p равно p[0].

В вашем случае *int_ptr равно int_ptr[0].

Если вы сделали то же самое с char_ptr (т.е. *char_ptr) у вас будет char_ptr[0], который представляет собой один символ, который также может быть напечатан с помощью %d:

printf("char_ptr (%p) --> '%d'\n", char_ptr, *char_ptr);

Это будет печатать десятичное представление первого символа в строке.

0 голосов
/ 19 апреля 2020

Вы также можете использовать выражение *char_ptr. Он имеет тип char, и выражение приведет к указанному символу, который является 'T' - первым символом сохраненного строкового литерала.

Это то же самое, что *int_ptr, который возвращает первый элемент выделенный целочисленный массив.

Что касается спецификатора преобразования %s, то он ожидает аргумент типа char *, указывающий на строку. С другой стороны, спецификатор преобразования %d ожидает объект типа int

. Вы можете использовать спецификатор преобразования %c. вывести только один символ указанной строки, например

printf( "%c", *char_ptr );
...