C: Как правильно объявить массив строк? - PullRequest
6 голосов
/ 29 июля 2009

Я видел оба:

const char*  arr = {"foo", "bar"};

и

const char*  arr[] = {"foo", "bar"};

Какой правильный и общепринятый способ?

В чем разница между двумя?

в чем разница между

   const char**arr = {"foo", "bar"};

и

    const char* arr[] = {"foo", "bar"};

и

   const char* * const arr = {"foo", "bar"};    

и

   const char* const * const arr = {"foo", "bar"};

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

Ответы [ 4 ]

12 голосов
/ 29 июля 2009

Это неверно, так как не имеет правильного уровня косвенности.

const char* arr = {"foo", "bar"};

Это не правильно, так как отсутствует =. Это похоже на определение функции.

const char* arr[] {"foo", "bar"};

Это обычная правильная форма.

const char* arr[] = { "foo", "bar" };

Редактировать

Вы не можете инициализировать указатель из агрегатного инициализатора (т.е. {..., ..., ...}). Вы можете сделать оба

const char* str1 = "A string";

и

const char str2[] = "Another string";

но это не так.

Строковый литерал имеет тип 'массив из n символов', поэтому его можно преобразовать в указатель, тогда как список инициализаторов на самом деле не массив, а просто способ инициализации массивов.

3 голосов
/ 29 июля 2009

По отношению к постоянству ...

const char* constValue = "foo";
constValue = "bar";
constValue[0] = 'x'; // will not work

char* const constPtr = "foo";
constPtr = "bar"; // will not work
constPtr[0] = 'x';

const char* const arr[] = { "foo", "bar", 0 }; // all const

'const char * const' часто является лучшим решением для чего-то полностью постоянного. Еще одной оптимизацией было бы также сделать это статическим, если оно объявлено в локальной области видимости. 0 ptr полезно для значения часового.

1 голос
/ 29 июля 2009

Есть несколько подходов. Самое простое - объявить массив массивов char следующим образом:

char strs[N][M + 1]; // M is max length of each string
...
strcpy(strs[i], "foo");

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

Другой подход заключается в объявлении массива указателей на char:

char *strs[N];
...
strs[i] = malloc(strlen("bar") + 1);
if (strs[i]) 
  strcpy(strs[i], "bar"); 

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

strs[j] = "foo";
strs[j][0] = 'b'; // may not be allowed on string literal

Вы можете динамически распределить весь smash:

char **strs = malloc(sizeof *strs * N);
for (i = 0; i < N; i++)
  strs[i] = malloc(SIZE + 1);

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

Обратите внимание, что лучшие практики в отношении malloc () различаются в C и C ++. В C считается плохой практикой приводить результат malloc (). Во-первых, это не нужно, поскольку указатели void неявно приводятся к другим типам указателей объектов. С другой стороны, он отключит диагностику, если вы забудете #include stdlib.h или у вас нет прототипа для malloc () в области видимости. Помните, что если C не видит прототип функции до того, как на нее ссылаются, он будет предполагать, что функция возвращает int, который не может быть неявно преобразован в тип указателя.

0 голосов
/ 29 июля 2009

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

//Allocate pointers for the strings
char **c = (char**)malloc(maxnumofstrs*sizeof(int));
//allocate memory for each string
for(int i = 0; i < maxnumofstrs; i++)
{
   c[i] = (char*)malloc(maxwidth);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...