2009-11-13 2 views
4

Примечание: На этот вопрос оказали влияние this answer.Почему компилятор не может получить длину строки для массива строк?

Ниже приведен правильный код C:

char myString[] = "This is my string"; 

Это будет выделять строку длины 18 (включая \0 характер) в стеке и присвоить указанное значение к нему.

Однако следующее:

char myStrings[][] = {"My 1st string", "My 2nd string", "My 3rd string"}; 

не является действительным, что дает ошибку «типу массив имеет неполный тип элемента».

Так что я должен указать массив как это:

char myStrings[][20] = {"My 1st string", "My 2nd string", "My 3rd string"}; 

Где 20 это число, которое больше, чем моей самой длинной строки.

Это компилируется и работает должным образом.

Если компилятор может динамически воспринимать длину строки при распределении одной строки в стеке, почему бы не сделать это для массива строк?

Edit:

Просто чтобы прояснить, это не является реальной проблемой жизни программирования я испытываю - это просто болезненное любопытство.

ответ

5

Одна вещь - «ощутить» длину одной строки. Другое дело, чтобы вычислить максимум длин многих строк. Существует определенная интуитивная качественная разница между ними. Таким образом, авторы языка, вероятно, решили, что первая простая и полезная, но последняя слишком сложна и менее полезна.

+0

+1 Хороший ответ - было больше похоже на то, о чем я думал. – LeopardSkinPillBoxHat

2

char myString [] = "..." - это 1-мерный массив, и он будет работать. char myStrings [] [] = {"...", "..."} - это двухмерный массив с (возможно) разной длиной строки, и это не сработает. char myStrings [] [20] - это 2D-массив с фиксированной длиной строки, и он будет работать.

Согласно стандартам C, компилятор не может определить длину строки в 2D-массивах.

Но я думаю, это возможно на Java.

+1

Это возможно в Java, потому что массивы строк всегда являются массивами указателей. – Zarel

4

Почему бы не сделать:

const char* myStrings[] = {"My 1st string", "My 2nd string", "My 3rd string"}; 
+1

Иногда вам нужны модифицируемые строки – pmg

+0

+1 @jeffamaphone очень приятно. @pmg, я думаю, намерение человека, задающего этот вопрос, состоит в том, чтобы создать постоянную строку. – Alphaneo

+0

Как отмечалось в pmg, это означало бы, что результирующие строки были доступны только для чтения. – LeopardSkinPillBoxHat

3

Поскольку компилятор видит это

char myStrings[][20] = {"My 1st string", "My 2nd string", "My 3rd string"}; 

в

char myStrings[][20] = {(char*), (char*), (char*)}; 

Затем Errrr ... хммм, с "магией компилятора", это может скопировать символы в те (char*) в массив myStrings [0] и myStrings [1], ....


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

Вы не можете иметь «неровные массивы» в С. Предположим, вы имели

char my_strings[][] = {"a", "ab", "abc", "foo foo fo foo foo", "abc", "ab", "a"}; 

my_strings[0] нуждается в том же пространстве, как my_strings[3], так как элементы языка мандаты массива должны быть смежными , и для этого требуется определенный размер каждого массива.

 
my_strings in memory 
    'a' '\0' '\0' ... '\0' but must be a definite size 
    'a' 'b' '\0' ... '\0' definite size 
    ... 
    'f' 'o' 'o' ... '\0' 
    ... 

Чтобы найти максимальный размер и инициализировать массив (ы), компилятор должен был бы сделать два прохода над строковых литералов.

+0

«избыточная» память символов для каждой строки не содержит мусора. Он будет заполнен нулями. Общая философия, используемая языком C, когда дело доходит до инициализации, состоит в том, что что-то либо полностью неинициализировано (все это мусор), либо полностью инициализировано (части, которые не имеют инициализатора, предоставленного пользователем, ноль инициализируются). Например, когда вы объявляете 'char s [100] =" a "' не только 's [0]' и 's [1]' инициализированы, но также и все элементы из 's [2]' to 's [ 99] 'гарантированно нулевой инициализации. – AnT

+0

Спасибо, Андрей. Отредактировал мой ответ – pmg

Смежные вопросы