инициализация символьных указателей

Смотрите на TestComplete.

14
задан nbro 11 March 2016 в 14:23
поделиться

10 ответов

Да, это хорошая идея. Google Code Style рекомендует:

  1. Инициализировать все ваши переменные, даже если они вам сейчас не нужны.
  2. Инициализировать указатели с помощью NULL , int ] на 0 и float на 0,0 - просто для лучшей читаемости.

     int i = 0;
    двойной х = 0,0;
    char * c = NULL;
    
14
ответ дан 1 December 2019 в 08:17
поделиться

Вы не можете сохранить строку в указателе.

Ваше определение mgt_dev_name хорошее, но вам нужно указать его где-нибудь с пробелом для вашей строки. Либо malloc () , либо используйте ранее определенный массив символов.

char *mgt_dev_name = NULL;
char data[4200];

/* ... */

mgt_dev_name = data; /* use array */

/* ... */

mgt_dev_name = malloc(4200);
if (mgt_dev_name != NULL) {
    /* use malloc'd space */
    free(mgt_dev_name);
} else {
    /* error: not enough memory */
}
4
ответ дан 1 December 2019 в 08:17
поделиться

Рекомендуется инициализировать все переменные.

4
ответ дан 1 December 2019 в 08:17
поделиться

Если вы спрашиваете, необходимо ли это или лучше инициализируйте переменную значением NULL , прежде чем устанавливать для нее что-то еще позже: нет необходимости инициализировать ее значением NULL , это не повлияет на функциональность вашей программы.

Обратите внимание, что в программировании важно понимать каждую строчку кода - почему она там и что именно делает. Дон'

3
ответ дан 1 December 2019 в 08:17
поделиться

Эта тема уже обсуждалась здесь:

http://www.velocityreviews.com/forums/t282290-how-to-initialize-a-char.html

Это относится к C ++, но может быть полезным и для вас.

2
ответ дан 1 December 2019 в 08:17
поделиться

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

в C: char * c = NULL;

в C ++: char * c = 0;

0
ответ дан 1 December 2019 в 08:17
поделиться

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

Да, рекомендуется инициализировать указатели 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 () еще более опасным, потому что вызывающие абоненты будут иметь некоторое заблуждение относительно безопасности. Вы не можете полагаться на практику «оптом», если не уверены, что каждая операция согласована.

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

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

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

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

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

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

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

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

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

Не полагайтесь на практику «оптом», если вы не уверены, что каждая операция согласована.

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

Не полагайтесь на практику «оптом», если вы не уверены, что каждая операция согласована.

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

0
ответ дан 1 December 2019 в 08:17
поделиться

Другой вариант - не определять переменную до того места в вашем коде, где у вас есть доступ к ее начальному значению. Поэтому вместо того, чтобы делать:

char *name = NULL;

...

name = initial_value;

Я бы изменил это на:

...

char *name = initial_value;

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

Тем не менее, это разрешено только начиная со стандарта c99 (он также действителен C ++). Чтобы включить функции c99 в gcc, вам нужно либо выполнить:

gcc -std=gnu99

, либо, если вы не хотите, чтобы расширения gcc были стандартными:

gcc -std=c99
3
ответ дан 1 December 2019 в 08:17
поделиться

Нет, это не лучшая практика, если я правильно понял ваш контекст.

Если ваш код действительно зависит от mgt_dev_name , имеющего начальное значение нулевого указателя, то, конечно, включение инициализатора в объявление - очень хорошая идея. Т.е. если ты d все равно придется делать это

char *mgt_dev_name;

/* ... and soon after */
mgt_dev_name = NULL;

, тогда всегда лучше использовать инициализацию вместо присваивания

char *mgt_dev_name = NULL;

Однако инициализация хороша только тогда, когда вы можете инициализировать свой объект с помощью значимого полезного ценность. Значение, которое вам действительно понадобится. В общем случае это возможно только в языках, которые допускают объявления в любой точке кода, C99 и C ++ являются хорошими примерами таких языков. К тому времени, когда вам понадобится ваш объект, вы обычно уже знаете соответствующий инициализатор для этого объекта, и поэтому можете легко придумать элегантное объявление с хорошим инициализатором.

С другой стороны, в C89 / 90 объявления могут быть только помещается в начало блока. На этом этапе в общем случае у вас не будет значимых инициализаторов для всех ваших объектов. Если вы просто инициализируете их чем-то, что-нибудь (например, 0 или NULL ) только для их инициализации ? Нет !!! Никогда не делайте бессмысленных вещей в своем коде. Это ничего не улучшит, что бы ни говорили вам различные «руководства по стилю». На самом деле бессмысленная инициализация может фактически скрыть ошибки в вашем коде, затрудняя их обнаружение и исправление.

Обратите внимание, что даже в C89 / 90 всегда полезно стремиться к лучшей локальности объявлений. Т.е. в известном практическом руководстве говорится: всегда делайте переменные настолько локальными, насколько это возможно. Не накапливайте все объявления ваших локальных объектов в самом начале функции, а лучше переместите их в начало самого маленького блока, который как можно плотнее охватывает все время жизни объекта. Иногда может быть даже хорошей идеей ввести фиктивный, в противном случае ненужный блок просто для улучшения локальности объявлений. Следование этой практике поможет вам предоставить хорошие полезные инициализаторы для ваших объектов во многих (если не в большинстве) случаев. Но некоторые объекты останутся неинициализированными в C89 / 90 только потому, что у вас не будет для них хорошего инициализатора в момент объявления. Не пытайтесь инициализировать их "чем-то" только ради их инициализации. Это ни к чему хорошему не приведет и может иметь негативные последствия.

Обратите внимание, что некоторые современные инструменты разработки (например, MS Visual Studio 2005) будут перехватывать доступ во время выполнения к неинициализированным переменным в отладочной версии кода. Я. Эти инструменты могут помочь вам обнаружить ситуации, когда вы обращаетесь к переменной до того, как она получит значимое значение, указывающее на ошибку в коде. Но, выполняя безусловную преждевременную инициализацию ваших переменных, вы по существу убиваете эту возможность инструмента и выметаете эти ошибки под ковер.

3
ответ дан 1 December 2019 в 08:17
поделиться

Мое объяснение состоит в том, что если вы не инициализируете с помощью NULL , а затем вообще забудете инициализировать, типы ошибок, которые вы получите в своем коде при разыменовании, будут очень значительными. труднее отследить из-за потенциального мусора, хранящегося в памяти в этот момент. С другой стороны, если вы инициализируете значение NULL , в большинстве случаев вы получите только ошибку сегментации , что лучше, учитывая альтернативу.

0
ответ дан 1 December 2019 в 08:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: