LINUX.ORG.RU

[РЕШЕНО] Как избавится от: предупреждение: приведение к типу указателя от целого другого размера [-Wint-to-pointer-cast]

 


1

1

При сборке на 64bit вот такой простой весчи такой варнинг - как избавится без костылей?

#include	<stdio.h>

int	main(int argc, char **argv)
{FILE	*f;

 f=(FILE *)popen("ls /","r");
 
 pclose(f);

return 1;}
Компиляю:
[faust@localhost C]$ gcc --version
gcc (GCC) 4.9.1 20140903 (prerelease)
Copyright (C) 2014 Free Software Foundation, Inc.
Это свободно распространяемое программное обеспечение. Условия копирования
приведены в исходных текстах. Без гарантии каких-либо качеств, включая 
коммерческую ценность и применимость для каких-либо целей.

[faust@localhost C]$ gcc -ansi 1.c
1.c: В функции «main»:
1.c:6:4: предупреждение: приведение к типу указателя от целого другого размера [-Wint-to-pointer-cast]
  f=(FILE *)popen("ls /","r");
    ^
[faust@localhost C]$

★★★★★

Последнее исправление: cetjs2 (всего исправлений: 2)

убрать -ansi или самому прописать прототип..

если полюбопытствуешь, то найдешь что этот ключик включает дефайн который в свою очередь отключает некоторые объявления в stdio (в частности popen)

и (уже второму за день) настоятельно советую -Wall -Wextra - они тебе вполне читабельно подскажут где не то

MKuznetsov ★★★★★
()

popen определён не в стандарте ANSI C, а в POSIX.1-2001. По этому с ключём -ansi и без указания соответствующих макросов у тебя в stdio.h нет прототипа для popen'а.

kim-roader ★★
()
Ответ на: комментарий от kim-roader

Есть. Если бы не было определения, то и ругань была бы на «неизвестный прототип» и прога не собралась.

  • Во первых, флаг -ansi или -std=c90 означают использование стандарта языка, а не к-либо библиотек (clib в данном случае) - не надо путать тёплое с мягким.
  • Во вторых, -ansi я писал спецом, что бы ненароком не вылезти за рамки стандарта (например, использование коммента «//» и т.п.).
  • В третьих, я же в названии темы написал флаг, отвечающий за енто, из чего следует, что отключения варнингов (для данного случая -Wint-to-pointer-cast) для меня неприемлемы, иначе и темы бы небыло.
  • И напоследок, предупреждение идёт на несоответствие размеров переменных, словно я int`у присваиваю long int, по крайней мере так шланг ругается.

Смотрел объявление в stdio.h, popen() обёрнута в дефайн: #define __USE_POSIX2, использование которого для меня ничего не меняет, что логично.

drfaust ★★★★★
() автор топика
Последнее исправление: drfaust (всего исправлений: 2)
Ответ на: комментарий от drfaust

UPD: Забыл показать шланг уже в 64бит системе:

[faust@localhost C]$ clang --version
clang version 3.5.0 (tags/RELEASE_350/final)
Target: x86_64-unknown-linux-gnu
Thread model: posix


[faust@localhost C]$ clang -ansi 1.c 
1.c:6:4: warning: cast to 'FILE *' (aka 'struct _IO_FILE *') from smaller integer type 'int' [-Wint-to-pointer-cast]
 f=(FILE *)popen("ls /","r");
   ^
1 warning generated.
[faust@localhost C]$ 

drfaust ★★★★★
() автор топика
Ответ на: комментарий от drfaust

Вам всё написали правильно. Раз popen() не определён в стандарте ANSI C, то компилятор и не находит определения для popen(), - вы ненароком вышли за стандарт.

И напоследок, предупреждение идёт на несоответствие размеров переменных

С -Wall компилировать не пробовали?

Sorcerer ★★★★★
()
Ответ на: комментарий от drfaust

ругань была бы на «неизвестный прототип» и прога не собралась.

Неа. Будет implicit function declaration. Ошибка сборки будет только если линкер не найдёт символ, но вот popen как раз таки есть.

i-rinat ★★★★★
()

-D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700

anonymous
()
Ответ на: комментарий от drfaust

Ну смотри. Я взял твой код, запихал в файл 1.c и скомпилировал

$ gcc -ansi 1.c -Wall
1.c: In function ‘main’:
1.c:6:2: warning: implicit declaration of function ‘popen’ [-Wimplicit-function-declaration]
  f=(FILE *)popen("ls /","r");
  ^
1.c:6:4: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
  f=(FILE *)popen("ls /","r");
    ^
1.c:8:2: warning: implicit declaration of function ‘pclose’ [-Wimplicit-function-declaration]
  pclose(f);
  ^
$

Видишь warning: implicit declaration of function ‘popen’ [-Wimplicit-function-declaration]? Это оно самое. Теперь убираем -ansi:

$ gcc 1.c -Wall
$ 
И всё начинает нормально работать. Пробуем ещё раз с ansi и разными макросами из man 3 popen
$ gcc -ansi 1.c -Wall -D_POSIX_C_SOURCE=2 
$ gcc -ansi 1.c -Wall -D_XOPEN_SOURCE
$ gcc -ansi 1.c -Wall -D_BSD_SOURCE
$ gcc -ansi 1.c -Wall -D_SVID_SOURCE
$
И действительно всё работает! Если до тебя до сих пор не дошло что происходит, то можно попробовать открыть man 1 gcc

-ansi In C mode, this is equivalent to -std=c90. ...

This turns off certain features of GCC that are incompatible with ISO C90 (when compiling C code), ..., and predefined macros such as «unix» and «vax» that identify the type of system you are using. It also enables the undesirable and rarely used ISO trigraph feature. For the C compiler, it disables recognition of C++ style // comments as well as the «inline» keyword. ... The macro «__STRICT_ANSI__» is predefined when the -ansi option is used. Some header files may notice this macro and refrain from declaring certain functions or defining certain macros that the ISO standard doesn't call for;

Теперь давай по пунктам?

Во первых, флаг -ansi или -std=c90 означают использование стандарта языка

Это не совсем верно. Эти флаги также означают включение и отключение определённых feature macros. Так, например, с флагом -std=c90 у тебя ошибка останется, а с -std=gnu90 — пропадёт.

Во вторых, -ansi я писал спецом, что бы ненароком не вылезти за рамки стандарта (например, использование коммента «//» и т.п.).

Не могу не процитировать тебе по этому поводу man gcc:

The -ansi option does not cause non-ISO programs to be rejected gratuitously. For that, -Wpedantic is required in addition to -ansi.

В твоём случае видимо, стоит использовать не -ansi, а -std=gnu90 -pedantic, чтобы у тебя работа компилятора не вызывала столько вопросов.

что отключения варнингов (для данного случая -Wint-to-pointer-cast) для меня неприемлемы

Тебе первый же коментатор сказал, что варнинги надо не отключать, а включать. Простое добавление -Wall решило бы все твои проблемы сразу и задёшево.

И напоследок, предупреждение идёт на несоответствие размеров переменных, словно я int`у присваиваю long int, по крайней мере так шланг ругается.

А чём я тебе и написал. В случае неявного определения функций (когда у них нет прототипа) типом возвращаемого значения считается int. А ты его кастуешь к типу FILE*

kim-roader ★★
()

-ansi - это древняя версия стандарта, нет смысла её использовать.

anonymous
()
Ответ на: комментарий от drfaust

Ты упорот.

если прототип функции не известен, считается, что она возвращает int. Судя по предупреждению компилятора, прототип не известен.

Если ты не исправишь правильно это место, твоя прога упадёт на 64-битах, инфа 99%.

anonymous
()
gcc -ansi -D_DEFAULT_SOURCE ...

ну или какой другой дефайн, открывающий __USE_POSIX2, без которого в glibc не видны прототипы popen/pclose. за подробностями - в /usr/include/features.h

ananas ★★★★★
()
Ответ на: комментарий от kim-roader

Видишь warning: implicit declaration of function ‘popen’ [-Wimplicit-function-declaration]? Это оно самое.

Это не тоже самое:

1.c:6:4: предупреждение: приведение к типу указателя от целого другого размера [-Wint-to-pointer-cast]

И не тоже самое в шланге

[faust@localhost C]$ clang -ansi 1.c
1.c:6:4: warning: cast to 'FILE *' (aka 'struct _IO_FILE *') from smaller integer type 'int' [-Wint-to-pointer-cast]


В stdio.h popen() обёрнут в __USE_POSIX2, но включение его cитуацию не меняет. К тому же прога собирается и работает и в 32 и в 64 бита (более сложный вариант - этот я урезал, что бы ничто не мешало).

Я так понял, что действительно компилеры считают эту функцию новой и решают её сделать return int; по стандарту, но почему-то не ругаются на отсутствие прототипа :( Включение -D_POSIX_C_SOURCE действительно меняет ситуацию.

drfaust ★★★★★
() автор топика
Последнее исправление: drfaust (всего исправлений: 1)
Ответ на: комментарий от drfaust

Это не тоже самое:
но почему-то не ругаются на отсутствие прототипа

Тебе уже сколько раз в этом треде сказали включить -Wall? Может ты хотя бы с пятого раза поймёшь? Включи -Wall и он тебе включит в том числе -Wimplicit-function-declaration, которое даст тебе нужный варнинг.

В stdio.h popen() обёрнут в __USE_POSIX2, но включение его cитуацию не меняет

Ты пробовал читать маны, раз чтение заголовочных файлов тебе не помогает? Ссылку на ман в котором написано какие надо включать макросы (man popen) я тебе уже давал, так что давай тебя теперь за ручку по хэдерам проведу.

В начале файла stdio.h есть такая красивая строчка # include <features.h> которая подключает файлик features.h. А этот файлик содержит в свою очередь вот такой вот код:

/* Undefine everything, so we get a clean slate.  */
#undef  __USE_ISOC11
#undef  __USE_ISOC99
#undef  __USE_ISOC95
#undef  __USE_ISOCXX11
#undef  __USE_POSIX
#undef  __USE_POSIX2
...
#if defined _POSIX_C_SOURCE && _POSIX_C_SOURCE >= 2 || defined _XOPEN_SOURCE
# define __USE_POSIX2   1
#endif
Что мы отсюда видим? Правильно. Мы видим, что определять вручную __USE_POSIX2 бесполезно. Более того: определять вручную feature test macros, которого нет в списке поддерживаемых твоего libc (почитай ещё man 7 feature_test_macros или документацию glibc) — это дурацкая идея.

kim-roader ★★
()
Ответ на: комментарий от drfaust

Дурик, уже давно приняты и действуют стандарты С от 1999 и 2011 годов, используй их. Или ты из тех пердунов, для которых Fortran = Fortran 66?

LongLiveUbuntu ★★★★★
()
Ответ на: комментарий от grondek

у него неявное объявление popen получается. А возвращаемое значение по-умолчанию int

Dark_SavanT ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.