#include<stdlib.h>
typedef struct
{
int *member;
} mystruct;
void main(int argc, char *argv)
{
mystruct **data;
data = (mystruct**)malloc(sizeof(mystruct*));
int c = 5;
printf("%x", data);
(*data)->member = &c;
printf("Member: %d", *((*data)->member));
}
Ошибка: Ошибка сегментации
Я ожидал, что в исходном коде будет напечатано «5».
Примечание: не применяйте malloc.
(*data)
хорошо, разыменовываем указатель, возвращенный malloc
. ->member
плохо, разыменование неинициализированной памяти (внутри чанка, возвращаемого malloc), неверный указатель.
Возьмите карандаш и лист бумаги и нарисуйте стрелки там, куда они указывают, и должно стать ясно, почему ваша программа не работает должным образом.
Ошибка: Ошибка сегментации
Я ожидал, что в исходном коде будет напечатано «5».
Это связано с тем, что вы выделили только указатель на свою структуру, и этот указатель не ссылается на допустимое место в памяти. Он вызывает неопределенное поведение (UB). Нужно выделить место под саму конструкцию.
int main(int argc, char *argv)
{
mystruct **data;
data = malloc(sizeof(*data));
*data = malloc(sizeof(**data));
int c = 5;
printf("%p %p", (void *)data, (void *)*data);
(*data)->member = &c;
printf("Member: %d", *((*data)->member)); //or*data[0]->member))
}
void main(....
недействителенsizeof
%p
для печати указателей. Указатели должны быть преобразованы в void *
В этом заявлении
data = (mystruct**)malloc(sizeof(mystruct*));
вы выделили память для одного указателя типа mystruct *
. Это неинициализированный.
Таким образом, разыменовав этот неинициализированный указатель, полученный выражением *data
(*data)->member = &c
вызывает неопределенное поведение.
По крайней мере, вы должны написать
data = (mystruct**)malloc(sizeof(mystruct*));
*data = malloc( sizeof( mystruct ) );
То есть вам нужно выделить память для объекта типа mystruct
элемент данных member
которого будет назначен.
Также обратите внимание на то, что использование спецификатора преобразования %x
для вывода указателя
printf("%x", data);
также вызывает неопределенное поведение. Вместо этого вам нужно написать
printf("%p\n", ( void * )data);
Или вы можете включить заголовок <inttypes.h>
и написать
#include <inttypes.h>
//...
printf("%" PRIxPTR "\n", ( uintptr_t )data);
спасибо, это действительно полезно. Все-таки хочу спросить, почему мы должны бросать (void*)
@ hoang15nguyen Это требование для спецификатора преобразования p. Из стандарта C «p Аргумент должен быть указателем на void. Значение указателя преобразуется в последовательность печатных символов способом, определяемым реализацией».
Хорошо, вы выделяете указатель на mystruct. На какую mystruct указывает этот указатель?