Перейти к содержанию

Warning достал !!!


Рекомендуемые сообщения

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

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 всего, но все равно - обидно! Кто-то может объяснить, что здесь не нравится компиллятору ?

Ссылка на комментарий
Поделиться на другие сайты

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, не должны изменяться

Ссылка на комментарий
Поделиться на другие сайты

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... И что это значит ?!

Ссылка на комментарий
Поделиться на другие сайты

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;

Ссылка на комментарий
Поделиться на другие сайты

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

Ссылка на комментарий
Поделиться на другие сайты

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 .

Ссылка на комментарий
Поделиться на другие сайты

Цитата:

Всё логично

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

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

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

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

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

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

Ссылка на комментарий
Поделиться на другие сайты

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

Цитата:

Всё логично

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

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

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

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

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

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

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

Ссылка на комментарий
Поделиться на другие сайты

Цитата:

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

А меня заело... 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;}
Ссылка на комментарий
Поделиться на другие сайты

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

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

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

Ссылка на комментарий
Поделиться на другие сайты

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

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

Ссылка на комментарий
Поделиться на другие сайты

  • 5 месяцев спустя...

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

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

30: Constant variable 'var4' must be initialized

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

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

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

const char var4 = '\0';
Ссылка на комментарий
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
×
×
  • Создать...