Jump to content
Sign in to follow this  
sv_lary

Warning достал !!!

Recommended Posts

Есть функция, описаная как :

int sqlite3_prepare(...4 параметра, а это пятый :  const char **pzTail     /* OUT: Pointer to unused portion of zSql */);

Я ее вызываю следующим образом :

char *pzTail;rc = sqlite3_prepare(..., &pzTail);

Компиллятор (GCC) выдает предупреждение :

Цитата:

warning: passing arg 5 of `sqlite3_prepare' from incompatible pointer type

Хоть это и warning всего, но все равно - обидно! Кто-то может объяснить, что здесь не нравится компиллятору ?

Share this post


Link to post
Share on other sites

sv_lary писал(а) Tue, 22 December 2009 09:01

Есть функция, описаная как :

int sqlite3_prepare(...4 параметра, а это пятый :  const char **pzTail     /* OUT: Pointer to unused portion of zSql */);

Я ее вызываю следующим образом :

char *pzTail;rc = sqlite3_prepare(..., &pzTail);

Компиллятор (GCC) выдает предупреждение :

Цитата:

warning: passing arg 5 of `sqlite3_prepare' from incompatible pointer type

Хоть это и warning всего, но все равно - обидно! Кто-то может объяснить, что здесь не нравится компиллятору ?

Если вы используете const для проверки на стадии компиляции изменения данных, то это нужно делать везде.

В вашем случае, определить перед вызовом функции.

const char *pzTail;

показывая компилятору, что данные, на которые указывает pzTail, не должны изменяться

Share this post


Link to post
Share on other sites

gogi писал(а) Tue, 22 December 2009 14:54

В вашем случае, определить перед вызовом функции.

const char *pzTail;

показывая компилятору, что данные, на которые указывает pzTail, не должны изменяться

Спасибо - помогло ! Но, честно говоря, абсолютно НЕ понятно.

Стандарт языка С. (Working Draft, 1997-11-21, WG14/N794 J11/97-158)

6.5.3 Type qualifiers

Syntax

type-qualifier:

const

If an attempt is made to modify an object defined with a const-qualified type through use of an lvalue with non-const-qualified type, the behavior is undefined. If an attempt is made to refer to an object defined with a volatile-qualified type through use of an lvalue with non-volatile-qualified type, the behavior is undefined.98

Описание функции из библиотеки SQLite3 : pzTail is made to point to the first byte past the end of the first SQL statement in zSql.

Т.е. определение языка утверждает, что квалификатор const запрещает использовать идентификатор в качестве l-value. А в описании функции совершенно ясно говорится, что значение этого идентификатора УСТАНАВЛИВАЕТСЯ внутри функции. Т.е. он ИСПОЛЬЗУЕТСЯ в качестве l-value... И что это значит ?!

Share this post


Link to post
Share on other sites

sv_lary писал(а) Wed, 23 December 2009 06:32

Т.е. определение языка утверждает, что квалификатор const запрещает использовать идентификатор в качестве l-value. А в описании функции совершенно ясно говорится, что значение этого идентификатора УСТАНАВЛИВАЕТСЯ внутри функции. Т.е. он ИСПОЛЬЗУЕТСЯ в качестве l-value... И что это значит ?!

const char ** var;

запрещает

**var= 'C';

но разрешает

*var= "String";

также разрешает

s= "String;

var= &s;

Для запрета последних используется

char * const * var;

и

char ** const var;

Share this post


Link to post
Share on other sites

Спасибо! Это надо просто выучить. Smile Потому, что понять такое - невозможно.. Smile Во всяком случае, после таких языков, как Pascal, Modula-2 или Ada...

Share this post


Link to post
Share on other sites

sv_lary писал(а) Thu, 24 December 2009 06:10

Спасибо! Это надо просто выучить. Smile Потому, что понять такое - невозможно.. Smile Во всяком случае, после таких языков, как Pascal, Modula-2 или Ada...

Многим нравится C как раз за такие вещи (Даёшь больше звёздочек!). Другие (выросшие на ассемблере любители низкоуровневого программирования), напротив, вовсе игнорируют const и ставят уровень предупреждений такой, чтобы компилятор молчал.

А запомнить, мне кажется просто.

Есть типы char, char*, char**...

Также есть типы char const ( он же const char), char* const, char** const. Всё логично Smile .

Share this post


Link to post
Share on other sites

Цитата:

Всё логично

Т.е. я эти примеры понял так :

const char ***var; // Запрещает ***var=

char * const ** var; // Запрещвет **var=

char ** const * var; // Запрещает *var=

char *** const var; // Запрещает var=

Или я опять ошибаюсь ?

Share this post


Link to post
Share on other sites

sv_lary писал(а) Fri, 25 December 2009 06:43

Цитата:

Всё логично

Т.е. я эти примеры понял так :

const char ***var; // Запрещает ***var=

char * const ** var; // Запрещвет **var=

char ** const * var; // Запрещает *var=

char *** const var; // Запрещает var=

Или я опять ошибаюсь ?

Это лекго проверить. )))

Share this post


Link to post
Share on other sites

Цитата:

Это лекго проверить.

А меня заело... Smile Я решил - ПРОВЕРИТЬ! И написал крохотную программку. Тексты, выданные компиллятором, я вставил прямо в текст программы в виде комментариев. Характерно, что сообщения об ОШИБКАХ появились именно там. где Вы и указывали. Хотя я смысла этого по прежнему и не понимаю... Но вот три дополнительных ВАРНИНГА меня убили... Sad Короче, смотрите сами :

int main(int argc, char argv[]) {    char        sym = '\a';    char     *p_sym = &sym;    char   **pp_sym = &p_sym;    char ***ppp_sym = &pp_sym;// 1. Запрещает ***var1= const char ***var1;     var1 = ppp_sym;	// предупреждение: несовместимый тип указателя в присваивании    *var1 = pp_sym;	// предупреждение: несовместимый тип указателя в присваивании    **var1 = p_sym;    ***var1 = sym;		// ошибка: assignment of read-only location ‘***var1’// 2. Запрещвет **var2=char * const ** var2;    var2 = ppp_sym;	// предупреждение: несовместимый тип указателя в присваивании    *var2 = pp_sym;    **var2 = p_sym;		// ошибка: assignment of read-only location ‘**var2’    ***var2 = sym;// 3. Запрещает *var3=char ** const * var3;    var3 = ppp_sym;    *var3 = pp_sym;	// ошибка: assignment of read-only location ‘*var3’    **var3 = p_sym;    ***var3 = sym;// 4.Запрещает var4=char *** const var4;     var4 = ppp_sym;	// ошибка: присваивание переменной ‘var4’, доступной только на чтение     *var4 = pp_sym;    **var4 = p_sym;    ***var4 = sym;}

Share this post


Link to post
Share on other sites

Этот результат был получен при использовании компиллятора :

$ cc --versioncc (GCC) 4.4.1 20090725 (Red Hat 4.4.1-2)Copyright © 2009 Free Software Foundation, Inc.

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

Share this post


Link to post
Share on other sites

sv_lary писал(а) Fri, 25 December 2009 11:12

Цитата:

Это лекго проверить.

А меня заело... Smile Я решил - ПРОВЕРИТЬ! И написал крохотную программку. Тексты, выданные компиллятором, я вставил прямо в текст программы в виде комментариев. Характерно, что сообщения об ОШИБКАХ появились именно там. где Вы и указывали. Хотя я смысла этого по прежнему и не понимаю... Но вот три дополнительных ВАРНИНГА меня убили... Sad Короче, смотрите сами :

int main(int argc, char argv[]) {    char        sym = '\a';    char     *p_sym = &sym;    char   **pp_sym = &p_sym;    char ***ppp_sym = &pp_sym;// 1. Запрещает ***var1= const char ***var1;     var1 = ppp_sym;	// предупреждение: несовместимый тип указателя в присваивании    *var1 = pp_sym;	// предупреждение: несовместимый тип указателя в присваивании    **var1 = p_sym;    ***var1 = sym;		// ошибка: assignment of read-only location ‘***var1’// 2. Запрещвет **var2=char * const ** var2;    var2 = ppp_sym;	// предупреждение: несовместимый тип указателя в присваивании    *var2 = pp_sym;    **var2 = p_sym;		// ошибка: assignment of read-only location ‘**var2’    ***var2 = sym;// 3. Запрещает *var3=char ** const * var3;    var3 = ppp_sym;    *var3 = pp_sym;	// ошибка: assignment of read-only location ‘*var3’    **var3 = p_sym;    ***var3 = sym;// 4.Запрещает var4=char *** const var4;     var4 = ppp_sym;	// ошибка: присваивание переменной ‘var4’, доступной только на чтение     *var4 = pp_sym;    **var4 = p_sym;    ***var4 = sym;}

Ошибки пойманы верно. Ради этого и задумывался const.

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

var1 = (char const ***)ppp_sym; // char*** -> char const ***

*var1 = (char const **)pp_sym; // char** -> char const **

var2 = (char * const **)ppp_sym; // char*** -> char * const **

Хотя мне кажется, достаточно было ограничиться предупреждениями при попытке обратного преобразования const char* -> char*

Почему нет предупреждений в трех других случаях?

**var1 = p_sym; // char* -> char const *

*var2 = pp_sym; // char** -> char * const *

var3 = ppp_sym; // char*** -> char ** const *

Этого я не знаю. Может, особенности реализации компилятора. Наверное, правильным является явно указать преобразования типа и в этих случаях.

Ну а в оставшихся все верно. Преобразования типа здесь не происходит.

***var2 = sym;

**var3 = p_sym;

***var3 = sym;

*var4 = pp_sym;

**var4 = p_sym;

***var4 = sym;

Проверил на gcc (Debian 4.3.2-1.1) 4.3.2

ошибки и предупреждения в тех же местах, что и у Вас.

Share this post


Link to post
Share on other sites

sv_lary писал(а) Fri, 25 December 2009 12:01

На Борланд-С упомянутые варнинги исчезли, но появлся свой :

30: Constant variable 'var4' must be initialized

Еще не лучше !!!

Переменная должна быть инициализирована. Можно этот кусок кода, на который он ругается, посмотреть?

Скорее всего нужно всего лишь указать значение переменной при её объявлении, что-то вроде:

const char var4 = '\0';

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
Sign in to follow this  

×
×
  • Create New...