2012-03-22 2 views
0

Я изучаю программирование сокетов, и я столкнулся с этим кодом.Confused about memset

struct addrinfo hints, *res, *p; 
int status; 
char ipstr[INET6_ADDRSTRLEN]; 

if (argc != 2) { 
    fprintf(stderr,"usage: showip hostname\n"); 
    return 1; 
} 

memset(&hints, 0, sizeof hints); 
hints.ai_family = AF_UNSPEC; // AF_INET or AF_INET6 to force version 
hints.ai_socktype = SOCK_STREAM; 

if ((status = getaddrinfo(argv[1], NULL, &hints, &res)) != 0) { 
    fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status)); 
    return 2; 
} 

Я понимаю все, кроме одного. Почему этот код memset'ed строковые подсказки, но не * res и * p?

+1

Лучшим стилем будет инициализация 'hints' вместо вызова' memset'. –

ответ

3

Указатель res должен быть заполнен функцией getaddrinfo и поэтому не нужно инициализировать нулем. hints, с другой стороны, необходимо инициализировать, поэтому установить всю структуру в нуль и затем установить только два поля, которые необходимо установить.

Как вы не используете p в своем коде - я не могу комментировать его.

0

Это не должно быть так, как вы только memset намекает на все 0s. Кроме того, res и p являются указателями, которые не располагаются в любом месте во время вызова memset.

Ожидаемое поведение. Дайте мне знать, каково ваше исключение, и я помогу вам лучше.

0

Почему этот код memset'ed подсказки структуры, но не * res и * p?

Потому что вы вызываете memset только один раз и передаете только & подсказки в качестве аргумента для этого memset.

memset(&hints, 0, sizeof hints); 

Если вы хотите MemSet * Res & * р, сначала нужно выделить память для таких же, как они onlypointers, а затем вам нужно вызвать MemSet отдельно для каждого из них, передавая их в качестве аргументов.

+0

Так что я могу memset * res, однако это не имеет смысла, потому что getaddrinfo все равно перезапишет? –

+0

Вы не можете memset '* res', потому что указатель недействителен (содержит« мусор », поскольку он не был инициализирован, что указывает на недопустимый« объект »). Вы можете перенести сам указатель ('res'), но так же легко назначить ему нуль (' res = 0; '), если вы хотите это сделать. И вы правы, вызов функции назначит новое значение 'res', когда оно вернется.- Разъяснение: тип 'res' - это' struct addrinfo * '(указатель на структуру addrinfo), тип' * res' - это 'struct addrinfo' (сама структура, а не указатель) – Attila

1

Описание getaddrinfo заявляет, что

The getaddrinfo() функция выделяет и инициализирует связанный список addrinfo структур, по одному для каждого сетевого адреса, который соответствует узлу и услуг, при условии каких-либо ограничений, налагаемых намеков, и возвращает указатель на начало списка в res.

Это означает, что вы не хотите, чтобы какая-либо другая информация была в hints, чем строго необходимо (в противном случае функция может вызвать нежелательный выход). Кроме того, «реальный» результат функции возвращается в res, что означает, что текущее содержимое res перезаписано, поэтому вам все равно, что было там до вызова функции (пока вы не собираетесь интерпретировать если функция не работает).

Поскольку элементы структуры (например, addrinfo) не инициализируются каким-либо образом при объявлении переменной этого типа, то hints изначально содержит «мусор» - все, что было в памяти, где выделена переменная. Таким образом, код вызывает memset, чтобы обнулить все элементы простым/быстрым способом (в отличие от установки переменных-членов равными нулю один за другим).