LINUX.ORG.RU

Какой тип возвращает memmem?


0

1

В программе есть строки:

#include <string.h>
...
char* where;
char* array;
char* needle;
size_t left, needlelength;
...
where = memmem( array, left, needle, needlelength);

На последнюю строку GCC выдаёт предупреждение:

warning: assignment makes pointer from integer without a cast

Если перед memmap добавить (char*) или (void*), компилируется без предупреждений.

Почему так происходит? Во всех мануалах написано, что memmem возвращает указатели. В заголовочных файлах она есть только в string.h:

extern void *memmem (__const void *__haystack, size_t __haystacklen, __const void *__needle, size_t __needlelen)

Система Ubuntu, gcc (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5, версия libc 2.12.1.

Заранее спасибо.

★★★★★

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

Ответ на: комментарий от arsi

Да, ошибся при копировании. В оригинале они каждый на своей строке.

question4 ★★★★★
() автор топика

1) Добавь следущие опции компилятору:

-Wall -Wextra -Wmissing-prototypes

2) Потом собери, и добавь ещё одну опцию:

-D_GNU_SOURCE

3) Затем открой ещё раз мануал и прочитай его внимательно

anonymous
()

Осмелюсь предположить, что это защита от дурака. void* это неизвестно на что указатель, и компилятор Вас информирует о том, что Вы его неявно привели к char*. А вдруг там инты лежат?;-))))

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

> Осмелюсь предположить, что это защита от дурака. void* это неизвестно на что указатель, и компилятор Вас информирует о том, что Вы его неявно привели к char*.

Тогда почему предупреждение пропадает после добавления (void*) тоже?

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

Опять таки осмелюсь предположить, что в этм случае компилятор умывает руки - раз Вы настаиваете, пусть будт void*. Но на самом деле надо читать стандарт, это уже какие то тонкие тонкости.

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

> 1) Добавь следущие опции компилятору:

-Wall -Wextra -Wmissing-prototypes

С -Wall пишет:

warning: implicit declaration of function ‘memmem’

А почему нет таких проблем с printf?

-D_GNU_SOURCE

Спасибо.

открой ещё раз мануал и прочитай его внимательно

В man gcc про _GNU_SOURCE не написано. В интернете — много не по делу. Ищу. Не подскажешь ли сразу, как сделать, чтобы оно применялось по умолчанию при каждом запуске GCC?

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

> Осмелюсь предположить, что это защита от дурака. void* это неизвестно на что указатель, и компилятор Вас информирует о том, что Вы его неявно привели к char*.

Большего бреда не видел. Вы вообще о C имеете представление? void* как раз для такого и был введён - для безболезненной возможности каста void* к другим типами.

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

> man memmem.

У меня его нету :) Набивал по памяти, ориентируясь на string.h.

Если этот же ман на die.net, то там не объясняется, что даёт #define _GNU_SOURCE. Хуже того, у меня был неприятный опыт, когда часть указанных в таких манах инклудов мешали :) (Если не путаю, там включалось что-то вроде string.h одновременно со strings.h.)

Сейчас роюсь на gnu.org, но интернет небыстрый. Поэтому повторяю вопрос: как в Убунту сделать _GNU_SOURCE (или эквивалентный набор ключей) настройкой по умолчанию?

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

>Если этот же ман на die.net, то там не объясняется, что даёт #define _GNU_SOURCE

Заголовочные файлы определяют прототип для memmem только если определен этот макрос. В отсутствии прототипа компилятор считает, что функция возвращает int. Попытка присвоить int указателю на char вызывает предупреждение.

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

> Большего бреда не видел. Завидую, Вы счастливый человек.

Вы вообще о C имеете представление? void* как раз для такого и был введён - для безболезненной возможности каста void* к другим типами.

Я? Нет, я на С не пишу (как мне тут давеча о питоне ответили). Просветите тогда меня, бестолочь, с чего этот варнинг вылетает.

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

О, огромное спасибо за такую полезную ссылку! Согласно нему, Ваш ник можно трактовать как «эго американского ракетного общества». Вы первая белка - космонавт?

Но тем не менее, почему вылетает этот варнинг я не понял.

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

>Просветите тогда меня

Компилятор не находит определения memmem (из-за того, что оно скрыто за _GNU_blabla), думает, что ты используешь тут же implicit-объявленную функцию memmem. При этом считается, что любая функция, явно не возвращающая какого-либо типа, по умолчанию всегда возвращает int. В итоге и получается «ворнинг: конверт фром инт то поинтер». А между указателями any* -> void* -> any* все всегда кастуется без проблем, анонимус правильно сказал.

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

>Вы первая белка - космонавт?

Не. Белку забанили. А каким дистрибутивом он пользовался, я не знаю, может и космонавтовским, кто знает...

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

Во, спасибо... мне мое объяснение тоже касалось весьма сомнительным, а про эту фичу с неявным возвратом инта я все время забываю.

То есть он определения не находит, но таки собирает просто с варнингом? Чудны дела твои, Господи... я то всегда наивно думал, что так делать низя;-)

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

>а про эту фичу с неявным возвратом инта я все время забываю.

Читать сообщения в ветке, походу, тоже забываете. Или делаете это по диагонали. :)

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

> То есть он определения не находит, но таки собирает просто с варнингом?

ты вообще си знаешь, нет? функции без прототипа считаются функциями, принимающими неопределённое количество аргументов и возвращающими int. ты вообще читать учебники/стандарты/маны пробовал? тебе букварь на 8-е марта подарить?

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

1) я свои предположения высказал ДО того, как появились сообщения, проливающие свет на.

2) инертность мышления - в голову бы не пришло, что может собраться вариант без объявления ф-ии, поэтому и проглядел. Впрочем это вполне ЛОРовская традиция - читать по диагонали или не читать вообще, яростно оттаивая свое мнение. Я просто стараюсь соответствовать;-)

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

Нет, этого не знал. Мне всегда казалось что С довольно строгий ЯП.

Выпейте уже валерьянки что ли, не надо так нервничать - хвост облысеет и выгонят с МКС за неопрятный внешний вид;-)

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

> Заголовочные файлы определяют прототип для memmem только если определен этот макрос.

Спасибо. Нашёл в string.h (надо было уменьшить шрифт или прокрутить на пару экранов вверх и вниз :) ):

#ifdef __USE_GNU
...
extern void *memmem (__const void *__haystack, size_t __haystacklen,
__const void *__needle, size_t __needlelen)
__THROW __attribute_pure__ __nonnull ((1, 3));
...
#endif

__USE_GNU определяется, если определён _GNU_SOURCE.

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