Jump to content

    

Функция sprintf

Значит Ваш компилятор в этом случае не проверяет соответствие типов передаваемых данных и аргументов функции. И плохо. Это его недостаток.

На самом деле типы соответствуют. Строковая константа имеет тип char[] без всяких const (сюрприз!), поэтому всё нормально. Это в C так, этот курьёз оставили, предположительно, из-за того, что к моменту изобретения const уже настрогали кучу кода, ломать его не хотелось. В то же время менять эту строку нельзя, поэтому компилятор мог бы предупреждать, но не по причине несоответствия типов, а по смыслу. В C++ всё проще: строка таки имеет тип const char[].

 

Почему?

Вообще в данном случае ничто не запрещает компилятору создать копию строки в ОЗУ перед вызовом функции. Просто он этого не делает (и хорошо, зачем лишнюю работу делать?). Предлагаю собрать небольшой пример и заглянуть в листинг дизассемблера.

Share this post


Link to post
Share on other sites
Вообще в данном случае ничто не запрещает компилятору создать копию строки в ОЗУ перед вызовом функции. Просто он этого не делает (и хорошо, зачем лишнюю работу делать?).

Хотя-бы потому, что это - идеологически было бы правильно.

Имхо: если функция только читает данные из переданного ей указателя - объявляй такой указатель с const, если и пишет - без const. А дальше - компилятор должен проверить соответствие типов и предупредить об ошибке. Что является только плюсом в отладке и уменьшении багов. Ну или автоматом устранить её, создав временный не-const объект на стеке или в static памяти. Ещё б желательно чтобы первое или второе поведение - определялось ключом компилятора.

А то, что почти все быдлокодеры будут писать без const и передавать туда константы - так это их проблемы.

 

Предлагаю собрать небольшой пример и заглянуть в листинг дизассемблера.

PS: Я уже проверял. Для IAR.

Share this post


Link to post
Share on other sites
Хотя-бы потому, что это - идеологически было бы правильно.

Идеология - штука субъективная. У нас гласность, свобода совести и плюрализм мнений.

Я довольно хорошо изучил язык Си, и мне он кажется вполне логичным и непротиворечивым. Есть там спорные моменты, но для них есть понятные обоснования, с которыми несложно согласиться. Обсуждаемый момент к спорным не могу отнести.

Share this post


Link to post
Share on other sites
Я довольно хорошо изучил язык Си, и мне он кажется вполне логичным и непротиворечивым.

Что-ж тут логичного, если char const t[] = "..."; Func(char *); Func(t); - вызывает ошибку, а Func("..."); - не вызывает?

Но при этом 2-й вариант хоть и компилируется, но может приводить к неработоспособному коду.

Хотя и в том и в другом случае данные одного и того же типа char const []. И даже более того - компилятор (линкёр?) могут объединить эти две константы в один объект в памяти.

Share this post


Link to post
Share on other sites
Но при этом 2-й вариант хоть и компилируется, но может приводить к неработоспособному коду.

Компилируйте в режиме C++, ни в чём себе не отказывайте :laughing:

Share this post


Link to post
Share on other sites
Компилируйте в режиме C++, ни в чём себе не отказывайте :laughing:

И...? У меня и так C++.

Share this post


Link to post
Share on other sites
Значит Ваш компилятор в этом случае не проверяет соответствие типов передаваемых данных и аргументов функции. И плохо. Это его недостаток.

Чего это он мой? Забери его себе :)

 

Но это не значит что все компиляторы так делают.

GCC и IAR компилят одинаково. Какой ещё эталон нужен?

 

Они передают в функцию const char* и если внутри работать как с char *, то матерятся.

void Printx(const uint8_t x,const char *s)
{
  const char *c;
  Goto(x);
  if (!(c=s)) return;
  while (*c)
  {
    WriteData(codepage[(uint8_t)*c]);
    c++;
  }
}

 

Вот в IAR AVR, с его кривой памятью, можно управлять процессом, кстати.

post-4140-1532517620_thumb.png

Share this post


Link to post
Share on other sites
Вот в IAR AVR, с его кривой памятью, можно управлять процессом, кстати.

В AVR память RAM и ROM находятся не в одном адресном пространстве, поэтому и есть явное разделение.

Share this post


Link to post
Share on other sites
Они передают в функцию const char* и если внутри работать как с char *, то матерятся.

Вы не поняли. Разговор о случае если аргумент функции - char *, а передаваемое значение: Func("xxx") (char const *). То компилятор не ругается. А по уму должен бы.

См. посты выше и https://electronix.ru/forum/index.php?showt...t&p=1574877

Share this post


Link to post
Share on other sites

Ещё как ругается. Если в Print(char *s); передать Print(" ");, то много нового о себе от компилятора узнаете.

 

Ругается, правда, только варнингом. Как и GCC :)

 

post-4140-1532520201_thumb.png

 

В IAR это звучит как

Warning[Pe2464]: conversion from a string literal to "char *" is deprecated Menu.cpp 54

Share this post


Link to post
Share on other sites
Ещё как ругается. Если в Print(char *s); передать Print(" ");, то много нового о себе от компилятора узнаете.

Как Вы добились сего??? Версия IAR? какие ключи компиляции?

У меня тоже IAR - проглатывает такое молча. Среди подавляемых варнингов Pe2464 - нету.

Share this post


Link to post
Share on other sites
Как Вы добились сего??? Версия IAR? какие ключи компиляции?

Перепроверил ещё раз. 8.22.2 выдаёт варнинг, и 8.30.1 соответственно тоже. Младше у меня нет. Проект С++ с настройками по умолчанию.

Share this post


Link to post
Share on other sites
Компилируйте в режиме C++, ни в чём себе не отказывайте :laughing:

Как Вы добились сего??? Версия IAR? какие ключи компиляции?

Проект С++ с настройками по умолчанию.

И...? У меня и так C++.

Очевидно, у вас таки не включен режим С++ :laughing:

Share this post


Link to post
Share on other sites
Очевидно, у вас таки не включен режим С++ :laughing:

Вам показать список типов из проекта? :D

Share this post


Link to post
Share on other sites
Очевидно, у вас таки не включен режим С++ :laughing:

post-38713-1532532743_thumb.png

ку?

Расширение си-файлов тоже: .cpp. Без скриншота поверите? B)

 

Перепроверил ещё раз. 8.22.2 выдаёт варнинг, и 8.30.1 соответственно тоже. Младше у меня нет. Проект С++ с настройками по умолчанию.

Ясно. У меня 7.80.4. Есть ещё 8.20 - завтра может проверю.

А всё что выше 8.22 - ставить не рискую. Почему - тема была тут: https://electronix.ru/forum/index.php?showt...=147939&hl=

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now