Short answer: Because C and C++ are different languages with different rules.
Long answer: In both cases the reason is that the array is too small for the string literal. The literal consists of the five visible characters, with a zero terminator on the end, so the total size is 6.
In C, you’re allowed to initialise an array with a string that’s too long; extra characters are simply ignored:
C99 6.7.8/14: An array of character type may be initialized by a character string literal, optionally enclosed in braces. Successive characters of the character string literal (including the terminating null character if there is room or if the array is of unknown size) initialize the elements of the array.
The compiler helpfully warns that the string is too large, since it almost certainly indicates an error; but it can’t reject the code unless you tell it to treat warnings as errors.
In C++, the initialiser isn’t allowed to be larger than the array:
C++11 8.5.2/2: There shall not be more initializers than there are array elements.
so, for that language, the compiler should give an error.
In both languages, when you want a character array to be the right size for a string literal initialiser, you can leave the size out and the compiler will do the right thing.
char a[] = "hello"; // size deduced to be 6
Aside from the missing commas in your set of initializers, why not just skip making it a 2-dimensional array of char
? You’re only passing the array data to strstr()
, and all it wants are null terminated strings. Why not use the more flexible:
char* array[] = {
"Becky Warre, 555-1223",
"Joe Looney, 555-0097",
"Geri Palmer, 555-8787",
"Lynn Presnell, 555-1212",
"Holly Gaddis, 555-8878",
"Sam Wiggins, 555-0998",
"Bob Kain, 555-8712",
"Tim Haynes, 555-7676",
"Warren Gaddis, 555-9037",
"Jean James, 555-4939",
"Ron Palmer, 555-2893",
NULL
};
Now that the array is just a set of pointers (and it’s terminated with a NULL pointer), the loop can look something like:
char *ptr = NULL;
int i;
for (i = 0; array[i] != NULL; i++)
{
ptr = strstr(array[i], search);
if (ptr != NULL)
cout << array[i];
}
One advantage of this is that you can add new strings to the data without having to update any corresponding ‘size’ numbers. And you’ll never have to worry about the compiler complaining that the array is too small in one dimension or another — it’ll just make the array the size it needs to be.
murtukov 10 / 10 / 5 Регистрация: 30.01.2013 Сообщений: 99 |
||||
1 |
||||
Передача двумерного массива в функцию25.02.2013, 04:17. Показов 3398. Ответов 7 Метки нет (Все метки)
Всем доброго времени суток! В Си, при объявлении двумерного массива, можно было сразу проинициализировать его значения:
Но в C++ такой вариант не прокатывает. Выскакивает следующая ошибка: error: initializer-string for array of chars is too long [-fpermissive] Что это значит?
__________________
0 |
Kuzia domovenok 3985 / 3255 / 909 Регистрация: 25.03.2012 Сообщений: 12,102 Записей в блоге: 1 |
||||
25.02.2013, 04:27 |
2 |
|||
Добавлено через 40 секунд
В Си, при объявлении двумерного массива, можно было сразу проинициализировать его значения: А в крестах что, нет?
0 |
murtukov 10 / 10 / 5 Регистрация: 30.01.2013 Сообщений: 99 |
||||
25.02.2013, 04:57 [ТС] |
3 |
|||
Добавлено через 40 секунд А в крестах что, нет? Вы что, наполовину читаете сообщение? Я же ясно написал: «Но в C++ такой вариант не прокатывает. Выскакивает следующая ошибка: error: initializer-string for array of chars is too long [-fpermissive]» Стало быть, что ТАКИМ ОБРАЗОМ нет. IDE: Code::Blocks 12.11 И на счет некорректного заголовка. Я сначала собирался запостить другой вопрос, но передумал, а изменить заголовок забыл.
0 |
52 / 41 / 16 Регистрация: 16.12.2012 Сообщений: 144 |
|
25.02.2013, 05:06 |
4 |
char mass[2][6] = { «Anton», «Misha» }; Я может быть ошибаюсь , но кажется нужно поставить «;» вместо «,» между миша и антон . Попробуйте , точно не помню.
0 |
alsav22 5493 / 4888 / 831 Регистрация: 04.06.2011 Сообщений: 13,587 |
||||
25.02.2013, 05:31 |
5 |
|||
Вы что, наполовину читаете сообщение? Я же ясно написал: Попробуйте написать код, как у него:
Миниатюры
1 |
5493 / 4888 / 831 Регистрация: 04.06.2011 Сообщений: 13,587 |
|
25.02.2013, 05:58 |
6 |
error: initializer-string for array of chars is too long [-fpermissive] Что строка для инициализации массива слишком длинная. » в конец строки компилятор сам добавляет.
2 |
kuli4ok 32 / 32 / 17 Регистрация: 10.10.2012 Сообщений: 88 |
||||
25.02.2013, 07:20 |
7 |
|||
Всем доброго времени суток! В Си, при объявлении двумерного массива, можно было сразу проинициализировать его значения:
Но в C++ такой вариант не прокатывает. Выскакивает следующая ошибка: error: initializer-string for array of chars is too long [-fpermissive] Что это значит? Всегда внимательно разбирайте сообщения компилятора, он лучше всякого форума вам скажет где вы ошиблись. Хотя бы просто в google переводчике перевести. Как вариант перевода: Инициализирующая строка слишком длинная для массива символов. Я думаю, вполне достаточно для того, что бы исправить ошибку. Добавлено через 1 минуту Не по теме: А потом все стучат в грудь и кричат «Нафига нам английский!?» …
1 |
442 / 410 / 132 Регистрация: 21.01.2012 Сообщений: 974 |
|
25.02.2013, 07:23 |
8 |
murtukov, а Вы что отличия не видите?
0 |
Следующая программа прекрасно компилируется в C с предупреждениями, но не компилируется в C ++. Зачем? Какова причина?
#include <stdio.h>
int main(void)
{
char a[5]="Hello";
a[0]='y';
puts(a);
for(int i=0;i<5;i++)
printf("%c",a[i]);
return 0;
}
Предупреждение:
Warning:[Error] initializer-string for array of chars is too long [-fpermissive] enabled by default
Но если программа скомпилирована как программа C ++, то компилятор C ++ выдает следующую ошибку:
[Error] initializer-string for array of chars is too long [-fpermissive]
Я использую компилятор GCC 4.8.1.
5
Решение
Краткий ответ: потому что C и C ++ — это разные языки с разными правилами.
Длинный ответ: в обоих случаях причина в том, что массив слишком мал для строкового литерала. Литерал состоит из пяти видимых символов с нулевым терминатором на конце, поэтому общий размер равен 6.
В C вы можете инициализировать массив слишком длинной строкой; лишние символы просто игнорируются:
C99 6.7.8 / 14: Массив символьного типа может быть инициализирован литералом символьной строки, необязательно заключенным в фигурные скобки. Последовательные символы литерала символьной строки (включая завершающий нулевой символ, если есть место или если массив имеет неизвестный размер) инициализируют элементы массива.
Компилятор предупреждает, что строка слишком велика, поскольку почти наверняка указывает на ошибку; но он не может отклонить код, если вы не скажете, чтобы он воспринимал предупреждения как ошибки.
В C ++ инициализатору не разрешено быть больше, чем массив:
C ++ 11 8.5.2 / 2: Инициализаторов не должно быть больше, чем элементов массива.
поэтому для этого языка компилятор должен выдать ошибку.
В обоих языках, когда вы хотите, чтобы символьный массив соответствовал размеру инициализатора строкового литерала, вы можете не указывать размер, и компилятор сделает все правильно.
char a[] = "hello"; // size deduced to be 6
22
Другие решения
Проблема в нижней строке
char a[5]="Hello";
Нет места для хранения завершающего нуля.
По умолчанию, gcc
не выдает никаких ошибок для этого случая с -fpermissive
опция включена. Так что компилирует нормально в C
,
Согласно требованию от языковых стандартов,
- За
C99
стандарт, глава 6.7.9, пункт 14,
Массив символьного типа может быть инициализирован символьным строковым литералом или строковым литералом UTF-8, необязательно заключенным в фигурные скобки. Последовательные байты строкового литерала (включая завершающий нулевой символ, если есть место или массив имеет неизвестный размер) инициализируют элементы массива.
- За
C++11
, глава 8.5.2, пункт 2
Инициализаторов не должно быть больше, чем элементов массива.
Итак, код компилируется (с предупреждениями) с gcc
, выдает ошибку с g++
,
10
Допустимая строка в C и C ++ должна иметь терминатор и в
char a[5]="Hello";
Там нет места для нулевого терминатора и не является допустимой строкой.
Так что это может не быть ошибкой в C, но вы обязательно столкнетесь с проблемами при использовании встроенных строковых функций, таких как strlen()
и семья.
5
Потому что «Привет» 6 char
с долго и г ++ без -fpermissive
не будет инициализировать 5 char
массив с ним, но GCC будет.
3
This sketch does not compile in the Arduino IDE
void setup() {
// put your setup code here, to run once:
}
struct test {
int i;
char variable[];
};
typedef struct test test;
test t = {
0, "hi"
};
void loop() {
// put your main code here, to run repeatedly:
}
Arduino throws
sketch_may09a:16: error: initializer-string for array of chars is too long [-fpermissive]
};
^
exit status 1
initializer-string for array of chars is too long [-fpermissive]
However compiling with g++ works just fine. How can I fix it? Or is there a principle reason why flexible array members are not supported?
Glorfindel
5731 gold badge7 silver badges18 bronze badges
asked May 9, 2019 at 19:31
4
Flexible array member is a C feature. It does not exist in C++. On top of that, the way you use it to declare and initialize a static struct of flexible size is non-standard even for C.
However, GNU-C language supports it as an extension. Also, newer versions of GCC (6 and higher) allow this in GNU-C++ code as an extension as well. But GCC 5.4.0 used by Arduino IDE doesn’t support this non-standard feature in C++ code.
If you flip through different GCC versions on Godbolt (https://godbolt.org/z/Iul7hD) you’ll see that support for this feature has always been present in C code, but for C++ code it first appeared in GCC 6.
This is why you were able to compile it with your standalone g++
compiler (which is apparently a much later version), but were unable to compile it in Arduino IDE.
It means that if you really want this non-standard code to compile in the current version of Arduino IDE, you have to place it into a .c
file. Or just specify the array size explicitly.
answered May 9, 2019 at 19:56
2
Maybe you’ve compiled it in g++ without any warnings enabled (or maybe it yeld warnings but was compiled). The arduino uses flags to consider all warnings as an error, so it won’t compile. It may wary for different platforms, I’ve got -fpermissive used (and I don’t like it at all).
That’s because size of struct must be known compile time and if you provide char variable[];
you’ll get zero sized array. Therefore anything biiger than nothing you’ll try to initialize for is too long.
Maybe you’re looking for something like this:
struct test {
int a;
const char * ptr;
};
test paramx {1, "some string"};
test paramy {2, "another string"};
test array[] = {{3,"three"}, {4, "four"}, {5,"five"}};
answered May 9, 2019 at 19:52
KIIVKIIV
4,2321 gold badge11 silver badges21 bronze badges
7
Короткий ответ: потому что C и С++ — разные языки с разными правилами.
Длинный ответ: В обоих случаях причина заключается в том, что массив слишком мал для строкового литерала. Литерал состоит из пяти видимых символов с нулевым терминатором на конце, поэтому общий размер равен 6.
В C вы можете инициализировать массив со слишком длинной строкой; дополнительные символы просто игнорируются:
C99 6.7.8/14: массив типа символа может быть инициализирован литералом строковой буквы, необязательно заключенным в фигурные скобки. Последовательные символы символьного строкового литерала (включая завершающий нулевой символ, если есть место или массив неизвестного размера) инициализируют элементы массива.
Компилятор предупреждает, что строка слишком велика, поскольку она почти наверняка указывает на ошибку; но он не может отклонить код, если вы не сообщите ему, чтобы он рассматривал предупреждения как ошибки.
В С++ инициализатор не может быть больше, чем массив:
С++ 11 8.5.2/2: не должно быть больше инициализаторов, чем элементов массива.
поэтому для этого языка компилятор должен сообщить об ошибке.
В обоих языках, когда вы хотите, чтобы массив символов был правильным размером для инициализатора строкового литерала, вы можете оставить размер, и компилятор выполнит правильные действия.
char a[] = "hello"; // size deduced to be 6
Following program compiles fine in C with warnings but fails in compilation in C++. Why? What is the reason?
#include <stdio.h>
int main(void)
{
char a[5]="Hello";
a[0]='y';
puts(a);
for(int i=0;i<5;i++)
printf("%c",a[i]);
return 0;
}
The warning:
Warning:[Error] initializer-string for array of chars is too long [-fpermissive] enabled by default
But if the program is compiled as C++ program then C++ compiler gives following error:
[Error] initializer-string for array of chars is too long [-fpermissive]
I am using GCC 4.8.1 compiler.
Short answer: Because C and C++ are different languages with different rules.
Long answer: In both cases the reason is that the array is too small for the string literal. The literal consists of the five visible characters, with a zero terminator on the end, so the total size is 6.
In C, you’re allowed to initialise an array with a string that’s too long; extra characters are simply ignored:
C99 6.7.8/14: An array of character type may be initialized by a character string literal, optionally enclosed in braces. Successive characters of the character string literal (including the terminating null character if there is room or if the array is of unknown size) initialize the elements of the array.
The compiler helpfully warns that the string is too large, since it almost certainly indicates an error; but it can’t reject the code unless you tell it to treat warnings as errors.
In C++, the initialiser isn’t allowed to be larger than the array:
C++11 8.5.2/2: There shall not be more initializers than there are array elements.
so, for that language, the compiler should give an error.
In both languages, when you want a character array to be the right size for a string literal initialiser, you can leave the size out and the compiler will do the right thing.
char a[] = "hello"; // size deduced to be 6
- Forum
- Beginners
- string logical question
string logical question
please see the following snippet. i get a garbage value as output.
void main()
{
char arr[7]=»network»;
printf(«%s»,arr);
}
I’m surprised it compiles. I get the following error.
error: initializer-string for array of chars is too long [-fpermissive]
"network"
is 8 chars. 7 letters + a null character » to mark the end of the string. If you change arr to size 8 it will probably work as you expected.
@peter87, whch compiler do you use?? i use turbo c++. i m getting wierd results. when i change the array size to six and hardcode it to «networ»
i get proper output as networ. i m confused.
Last edited on
I use GCC.
I said you should change the size to 8. If you change the string to «networ» you should change the size to 7.
If you leave out the size the compiler will automatically make the array big enough to store the string.
What your compiler seems to be doing is that if the array is shorter than the string it just ignores the characters that doesn’t fit, so in your original code arr will contain all characters in «network» except for the last character, the null character. When you print the array it will go through the characters one by one and stop when it finds a null character. arr doesn’t contain a null character so it just continue printing the bytes after the array, which is why you got garbage output.
i don’t think you should get proper results.
a c-string must be 1 character longer than its content, this extra slot is used to contain the null terminator.
if your compiler doesn’t care about this initialization and still compiles the program, and if you send the string to the output stream, you should get the phrase «network» followed by multiple garbage characters.
why is this behavior:
the output function keeps printing characters until it reaches a null character, which tells it to stop printing.
if your string doesn’t contain such character, then you’re on a date with your luck, you might eventually get an access violation error.
try [] = «network»
Topic archived. No new replies allowed.