инициализация указателей на символы - PullRequest
12 голосов
/ 02 ноября 2009

У меня есть указатель на символ, который будет использоваться для хранения строки. Это используется позже в программе.

Я объявил и инициализировал так:

char * p = NULL;

Мне просто интересно, если это хорошая практика. Я использую gcc 4.3.3.

Ответы [ 12 ]

0 голосов
/ 04 ноября 2009

Предпочтительные стили:

в С: char * c = NULL;

в C ++: char * c = 0;

0 голосов
/ 02 ноября 2009

Есть несколько хороших ответов на этот вопрос, один из них был принят. В любом случае я собираюсь ответить, чтобы расширить практические вопросы.

Да, хорошей практикой является инициализация указателей в NULL, а также установка указателей в NULL после того, как они больше не нужны (т.е. освобождены).

В любом случае очень полезно иметь возможность проверить указатель перед разыменованием его. Допустим, у вас есть структура, которая выглядит следующим образом:

struct foo {
    int counter;
    unsigned char ch;
    char *context;
};

Затем вы пишете приложение, которое порождает несколько потоков, каждый из которых работает (безопасно) с одной распределенной структурой foo, используя взаимное исключение.

Поток A получает блокировку для foo, увеличивает счетчик и проверяет значение в ch. Он не находит его, поэтому он не выделяет (или не изменяет) контекст. Вместо этого он сохраняет значение в ch, чтобы поток B мог выполнять эту работу.

Поток B Видит, что счетчик был увеличен, отмечает значение в ch, но не уверен, что поток A сделал что-то с контекстом. Если контекст был инициализирован как NULL, поток B больше не должен заботиться о том, что сделал поток A, он знает, что контекст безопасен для разыменования (если не NULL) или распределения (если NULL) без утечки.

Поток B делает свое дело, поток A читает его контекст, освобождает его, а затем повторно инициализирует его в NULL.

То же самое относится и к глобальным переменным без использования потоков. Хорошо иметь возможность тестировать их в различных функциях перед разыменованием (или пытаться выделить их, что приводит к утечке и неопределенному поведению в вашей программе).

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

Единственный раз, когда я видел "уродливый" случай, когда полагался на инициализированный указатель (до и после использования), это что-то вроде этого:

void my_free(void **p)
{
    if (*p != NULL) {
        free(*p);
        *p = NULL;
    }
}

Мало того, что на жестких платформах разыменовывается указатель типа «наказание», этот код делает функцию free () еще более опасной, поскольку вызывающие абоненты будут иметь некоторое заблуждение относительно безопасности. Вы не можете полагаться на практику «оптом», если не уверены, что каждая операция согласована.

Вероятно, гораздо больше информации, чем вы на самом деле хотели.

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