class A {
public void f(String s) {...}
public void f(Integer i) {...}
}
class B extends A {
public void f(Object o) {...} // Which A.f should this override?
}
В стандарте C ++ для символьных массивов 8.5.2 / 2 указано:
Инициализаторов не должно быть больше, чем элементов массива.
В стандарте C99: 6.7.8 / 2 Инициализация говорит:
Ни один инициализатор не должен пытаться предоставить значение для объекта, не содержащегося в сущности. инициализируется
C90 6.5.7 Инициализаторы говорят о том же.
Однако обратите внимание, что для C (как C90, так и C99) завершающий символ '\ 0' будет помещен в массив , если есть место . Это не ошибка, если терминатор не подходит (C99 6.7.8 / 14: «Последовательные символы литерала символьной строки (включая завершающий нулевой символ, если есть место или если массив неизвестного размера) инициализируют элементы массив ").
С другой стороны, в стандарте C ++ есть пример, который указывает, что ошибка должна быть диагностирована, если нет места для завершающего символа.
в любом случае это должно быть диагностировано как ошибка во всех компиляторах:
char str[5] = "fast enough";
] Возможно, компиляторы до ANSI не были такими строгими, но любой достаточно современный компилятор должен это диагностировать.
Ответ на процитированный вами вопрос неверен. Правильный ответ: «Нет. Код не будет компилироваться» , если предположить, что компилятор C формально правильный (в отличие от особенностей какого-то конкретного компилятора).
Язык C не позволяет использовать слишком длинные строки литерал для инициализации массива символов определенного размера. Единственная гибкость, допускаемая здесь языком, - это завершающий символ \ 0
. Если массив слишком короткий для размещения завершающего \ 0
, завершающий \ 0
отбрасывается без уведомления. Но фактические буквенные строковые символы нельзя отбросить. Если литерал слишком длинный, это нарушение ограничения, и компилятор должен выдать диагностическое сообщение.
char s1[5] = "abc"; /* OK */
char s2[5] = "abcd"; /* OK */
char s3[5] = "abcde"; /* OK, zero at the end is dropped (ERROR in C++) */
char s4[5] = "abcdef"; /* ERROR, initializer is too long (ERROR in C++ as well) */
Кто бы ни написал вашу "книгу" действительно знал, о чем они говорили (по крайней мере, по этой конкретной теме). То, что они заявляют в ответе, совершенно неверно.
Примечание: Использование слишком длинных инициализаторов строк запрещено в C89 / 90, C99 и C ++. Однако C ++ в этом отношении еще более ограничен. C ++ запрещает отбрасывать завершающий символ \ 0
, а C позволяет отбрасывать его, как описано выше.
Ваша книга должна быть довольно старой, потому что gcc выдает предупреждение даже без -Wall
включен:
$ gcc c.c c.c: In function `main': c.c:6: warning: initializer-string for array of chars is too long
Если мы немного обновим программу:
#include <stdio.h>
int main(int argc, char **argv)
{
char str[5] = "1234567890";
printf("%s\n", str);
return 0;
}
Мы видно, что gcc обрезает строку до указанной вами длины; Я предполагаю , что там происходит как '\ 0'
, где str [6]
будет, потому что в противном случае мы должны видеть мусор после 5; но, возможно, gcc неявно делает str
массивом длины 6 и автоматически вставляет туда '\ 0'
- я не уверен.
$ gcc c.c && ./a.exe c.c: In function `main': c.c:6: warning: initializer-string for array of chars is too long 12345
Потому что «достаточно быстро» просто указатель на строку с завершающим нулем. Компилятору слишком сложно определить, выйдет ли когда-либо присваивание char * или char [] за пределы массива.
Проверка привязки к массиву происходит во время выполнения, а не во время компиляции. Компилятор не имеет возможности выполнить статический анализ приведенного выше кода, который был бы необходим для предотвращения ошибки.
ОБНОВЛЕНИЕ: По-видимому, приведенное выше утверждение верно для некоторых компиляторов, а не для других. Если в вашей книге написано, что он будет компилироваться, значит, это относится к компилятору, который не выполняет проверку.
Что происходит? Вы пытаетесь инициализировать символьный массив с большим количеством символов, чем в массиве есть место. Вот как это работает:
char str[5];
Объявляет символьный массив из пяти символов.
char str[5] = "fast enough";
Вторая часть '= "достаточно быстро";' затем пытается инициализировать этот массив значением «достаточно быстро». Это не сработает, потому что «достаточно быстро» длиннее, чем массив.
Однако он будет компилироваться. Компиляторы C и C ++ обычно не могут выполнять проверку границ массивов за вас, и переполнение массива является одной из наиболее распространенных причин ошибок сегментации. [edit] Как заметил Марк Рушаков, очевидно, что в некоторых случаях более новые версии выдают предупреждения. [/ edit] Это может привести к сбою при попытке запустить его, скорее я думаю, что массив просто инициализируется "быстро".