fopen_s()
От: niXman Ниоткуда https://github.com/niXman
Дата: 22.05.19 08:01
Оценка:
привет!

скажите, я правильно понимаю, fopen_s() это M$ расширение?
смущает то, что гуглится и такое...

как вообще это использовать для разных компиляторов?
типа такого?:
#ifdef __STDC_WANT_LIB_EXT1__
# define my_fopen(h, p, m) \
   std::fopen_s(&h, p, m)
#else
# define my_fopen(h, p, m) \
   h = std::fopen(p, m)
#endif // __STDC_WANT_LIB_EXT1__
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re: fopen_s()
От: GhostCoders Россия  
Дата: 22.05.19 08:08
Оценка:
Здравствуйте, niXman, Вы писали:

X>скажите, я правильно понимаю, fopen_s() это M$ расширение?

Было M$ расширение, теперь стало стандартом... точно не помню каким 11, 14 или 17...
Третий Рим должен пасть!
Отредактировано 22.05.2019 8:09 GhostCoders . Предыдущая версия .
Re[2]: fopen_s()
От: niXman Ниоткуда https://github.com/niXman
Дата: 22.05.19 08:19
Оценка:
Здравствуйте, GhostCoders, Вы писали:

так и как юзать сабж на разных платформах и компиляторах?
тут пишут что если реализация опеределяет макропеременную __STDC_LIB_EXT1__. у меня она не определена, с++11.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re: fopen_s()
От: niXman Ниоткуда https://github.com/niXman
Дата: 22.05.19 08:23
Оценка:
может просто проверять на M$ компилятор и использовать макрос, который я привет выше?
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[2]: fopen_s()
От: Maniacal Россия  
Дата: 22.05.19 08:31
Оценка:
Здравствуйте, niXman, Вы писали:

X>может просто проверять на M$ компилятор и использовать макрос, который я привет выше?


На stackoverflow вообще предлагают реализовать в виде функции

errno_t fopen_s(FILE **f, const char *name, const char *mode) {
    errno_t ret = 0;
    assert(f);
    *f = fopen(name, mode);
    /* Can't be sure about 1-to-1 mapping of errno and MS' errno_t */
    if (!*f)
        ret = errno;
    return ret;
}


если спереди добавить #ifdef __STDC_WANT_LIB_EXT1__, то можно во всей программе юзать fopen_s
Re[3]: fopen_s()
От: niXman Ниоткуда https://github.com/niXman
Дата: 22.05.19 08:35
Оценка:
Здравствуйте, Maniacal, Вы писали:

M>На stackoverflow вообще предлагают реализовать в виде функции


согласно этому, ошибку выдает сам компилятор. так что добавлением одноименной функции, думаю, проблему не решить. потому я и думаю, что может просто детектить M$-compiler и подсовывать ему именно std::fopen_s()?
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re: fopen_s()
От: watchmaker  
Дата: 22.05.19 09:56
Оценка:
Здравствуйте, niXman, Вы писали:

X>скажите, я правильно понимаю, fopen_s() это M$ расширение?

Это опциональная функция языка C11. И по прежнему расширение в vc компиляторе (с чуть другим и нестандартным поведением).

X>как вообще это использовать для разных компиляторов?

X>типа такого?:
X>
X>#ifdef __STDC_WANT_LIB_EXT1__
X># define my_fopen(h, p, m) \
X>   std::fopen_s(&h, p, m)
X>#else
X># define my_fopen(h, p, m) \
X>   h = std::fopen(p, m)
X>#endif // __STDC_WANT_LIB_EXT1__
X>

В этом коде всё плохо :)
Судя по нему тут попытка смешать использование C и C++.
Но в стандарте С++ явно сказано про эту функцию из С (как и про многие другие), что они не определены в пространстве имён std.


X>#ifdef __STDC_WANT_LIB_EXT1__

Эта проверка тоже почти наверное ошибка. Этот макрос определяется пользователем. Он сам может задать его в любое целочисленное значение. Какой смысл его проверять?

В языке С эта функция будет доступна, если пользователь задал __STDC_WANT_LIB_EXT1__ в 1 перед первым включением stdio.h, а сама библиотека в свою очередь определила макрос __STDC_LIB_EXT1__.
Плюс в языке С++ наличие этих функций при включении любого C++ заголовочного файла — implementation defined. (с практической точки зрения это означает, что не стоит в С++ переиспользовать эти имена для своего кода — они могут конфликтовать с внезапно приехавшими определениями из какого-то случайного include).

Короче, тут в первую очередь стоит определиться на каком языке ты пишешь: на С или на С++. Ну и на какой версии. Это разные языки!
Re[2]: fopen_s()
От: Zhendos  
Дата: 22.05.19 10:09
Оценка:
Здравствуйте, GhostCoders, Вы писали:

GC>Здравствуйте, niXman, Вы писали:


X>>скажите, я правильно понимаю, fopen_s() это M$ расширение?

GC>Было M$ расширение, теперь стало стандартом... точно не помню каким 11, 14 или 17...

https://en.cppreference.com/mwiki/index.php?title=Special%3ASearch&search=fopen_s

поиск по имени ничего не дает, а на сайте даже будущий c++20 описан.
Re[2]: fopen_s()
От: Ops Россия  
Дата: 22.05.19 10:19
Оценка:
Здравствуйте, watchmaker, Вы писали:

X>>#ifdef __STDC_WANT_LIB_EXT1__

W>Эта проверка тоже почти наверное ошибка. Этот макрос определяется пользователем. Он сам может задать его в любое целочисленное значение. Какой смысл его проверять?

По стандарту, двойное подчеркивание в начале имени зарезервировано для реализации. И если такой макрос определяется пользователем, то плохо именно это.
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Re[2]: fopen_s()
От: niXman Ниоткуда https://github.com/niXman
Дата: 22.05.19 13:17
Оценка:
Здравствуйте, watchmaker, Вы писали:

ну да, fopen_s() — Си`шная функция.
остальные ошибки из-за спешки...

> В языке С эта функция будет доступна, если пользователь задал __STDC_WANT_LIB_EXT1__ в 1 перед первым включением stdio.h, а сама библиотека в свою очередь определила макрос __STDC_LIB_EXT1__.


а почему ты думаешь что в этом порядке?
мне почему-то кажется, что реализация должна определять __STDC_LIB_EXT1__, и только потом, юзер задетектив это, определяет __STDC_LIB_EXT1__. ну...согласно этому. но и тут все мутно...
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[3]: fopen_s()
От: niXman Ниоткуда https://github.com/niXman
Дата: 22.05.19 13:17
Оценка:
Здравствуйте, Zhendos, Вы писали:

Z>поиск по имени ничего не дает, а на сайте даже будущий c++20 описан.


вот оно где: https://en.cppreference.com/w/c/io/fopen
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[3]: fopen_s()
От: niXman Ниоткуда https://github.com/niXman
Дата: 22.05.19 13:21
Оценка:
Здравствуйте, Ops, Вы писали:

Ops>По стандарту, двойное подчеркивание в начале имени зарезервировано для реализации. И если такой макрос определяется пользователем, то плохо именно это.


у меня есть такое правило: каждый макрос, который define`ится и undef`айнится в одном файле — может зваться как угодно(лишь бы без конфликтов), но макрос, который только define`ится — должен начинаться с двойного подчеркивания и префикса в виде имени проекта. посему, думаю, что в стандарте вряд ли найдется макрос с именем __YAS_*
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re: fopen_s()
От: niXman Ниоткуда https://github.com/niXman
Дата: 22.05.19 13:26
Оценка:
пока что сделал так:
#ifdef _MSC_VER
# define __YAS_FOPEN(h, p, m) \
  ::fopen_s(&h, p, m)
#else
# define __YAS_FOPEN(h, p, m) \
  h = std::fopen(p, m)
#endif // _MSC_VER


код компилится M$-компилятором, но вот на первом тесте использующим ввод/вывод ловлю ошибку(appveyor): open file error
похоже, файл не открывается... нужно MSVC установить на машину...
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Отредактировано 22.05.2019 13:27 niXman . Предыдущая версия .
Re[4]: fopen_s()
От: Ops Россия  
Дата: 22.05.19 13:40
Оценка: +2
Здравствуйте, niXman, Вы писали:

X>у меня есть такое правило: каждый макрос, который define`ится и undef`айнится в одном файле — может зваться как угодно(лишь бы без конфликтов), но макрос, который только define`ится — должен начинаться с двойного подчеркивания и префикса в виде имени проекта. посему, думаю, что в стандарте вряд ли найдется макрос с именем __YAS_*


В стандарте покрыты все имена __*, так что это UB, хотя шансов, что оно когда-нибудь выстрелит, может и нет.

Each name that contains a double underscore __ or begins with an underscore followed by an uppercase letter is reserved to the implementation for any use.

Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Re[3]: fopen_s()
От: watchmaker  
Дата: 22.05.19 16:29
Оценка:
Здравствуйте, Ops, Вы писали:

Ops>Здравствуйте, watchmaker, Вы писали:


X>>>#ifdef __STDC_WANT_LIB_EXT1__

W>>Эта проверка тоже почти наверное ошибка. Этот макрос определяется пользователем. Он сам может задать его в любое целочисленное значение. Какой смысл его проверять?

Ops>По стандарту, двойное подчеркивание в начале имени зарезервировано для реализации. И если такой макрос определяется пользователем, то плохо именно это.

Если не троллишь, то советую посмотреть rationale для этого изменения: http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1173.pdf
Или заглянуть в стандарт, где есть примеры правильного кода, где именно в пользовательском коде определяется значение макроса.


Имя __STDC_WANT_LIB_EXT1__ действительно зарезервировано в стандарте языка C. И зарезервировано оно именно для пользовательского использования (как, вообще говоря, задумано и для всёго семейтсва __STDC_WANT_*).
Если пользователь его определил и его значение 0, то секция Annex K из стандарта не действует. Если определил и его значение 1, то становятся доступны определения из секции Annex K (при условии, что реализация в свою очередь выставит __STDC_LIB_EXT1__). Если макрос __STDC_WANT_LIB_EXT1__ не определён пользователем, то реализация может на своё усмотрение трактовать его значение как 0 или 1 (implementation defined).



Почему для макроса __STDC_WANT_LIB_EXT1__ было выбрано имя из зарезервированного пула имён?
Как раз по той причине, что эти имена уже были зарезервированы. И следовательно в корректном пользовательском коде они не должны встречаться. А значит вводя новое имя макроса в новой версии языка нет риска сломать обратную совместимость.
Re: fopen_s()
От: pagid Россия  
Дата: 24.05.19 04:50
Оценка:
Оно тебе нужно? Непременно использовать fopen_s под MSVC. Или весь сыр-бор из-за варнингов на fopen()?
Re[2]: fopen_s()
От: niXman Ниоткуда https://github.com/niXman
Дата: 27.05.19 16:05
Оценка:
Здравствуйте, pagid, Вы писали:


P>Или весь сыр-бор из-за варнингов на fopen()?


именно.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[3]: fopen_s()
От: Zhendos  
Дата: 27.05.19 16:16
Оценка:
Здравствуйте, niXman, Вы писали:

X>Здравствуйте, pagid, Вы писали:



P>>Или весь сыр-бор из-за варнингов на fopen()?


X>именно.


Так первый шаг при разработке с помощью VS это отключение этих предупреждений,
потому что использование "_s" функций превратит код в непереносимый.
Re[3]: fopen_s()
От: pagid Россия  
Дата: 27.05.19 17:45
Оценка:
Здравствуйте, niXman, Вы писали:

X>именно.

А точно разумно использовать в переносимом коде специфические функции и городить из них огород, если есть одинаковые? На мой взгляд, предупреждения недостаточная для этого причина.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.