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

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

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

char * p = NULL;

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

Ответы [ 12 ]

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

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

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

    int i = 0;
    double x = 0.0;
    char* c = NULL;
    
4 голосов
/ 02 ноября 2009

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

Ваше определение 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 голосов
/ 02 ноября 2009

Хорошей практикой является инициализация всех переменных.

3 голосов
/ 03 ноября 2009

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

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

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 голосов
/ 03 ноября 2009

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

char *name = NULL;

...

name = initial_value;

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

...

char *name = initial_value;

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

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

gcc -std=gnu99

или если вы не хотите расширений gcc для стандарта:

gcc -std=c99
3 голосов
/ 02 ноября 2009

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

Обратите внимание, что в программировании важно понимать каждую строку кода - почему она существует и что именно она делает. Не делайте вещи, не зная, что они значат, или не понимая, почему вы их делаете.

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

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

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

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

0 голосов
/ 03 мая 2019

Всегда хорошо инициализировать переменные-указатели в C ++, как показано ниже:

int *iPtr = nullptr;
char *cPtr = nullptr;

Поскольку инициализация, описанная выше, поможет в условиях, подобных приведенным ниже, поскольку nullptr может быть преобразовано в bool , в противном случае ваш код будет выдавать некоторые предупреждения компиляции или неопределенное поведение:

if(iPtr){
   //then do something.
}

if(cPtr){
  //then do something.
}
0 голосов
/ 03 января 2016

Инициализация переменных, даже если они вам не нужны, - это хорошая практика. Обычно мы инициализируем указатели в NULL, int в 0 и плавающие в 0.0 как соглашение.

int* ptr = NULL;
int i = 0;
float r = 0.0;
0 голосов
/ 09 июня 2010

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

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