Почему getcwd() не соответствует требованиям ISO С++?
В этой статье MSDN указано, что getcwd() устарел и что вместо него следует использовать совместимый с ISO С++ _getcwd, что вызывает вопрос: что делает getcwd() не совместимым с ISO?
Ответы
Ответ 1
Функции, не указанные в стандарте, должны иметь префикс подчеркивания как указание на то, что они являются расширениями, специфичными для поставщика, или придерживаются стандарта, отличного от ISO. Таким образом, "соблюдение" здесь означало, что Microsoft добавляет знак подчеркивания к названию этой конкретной функции, поскольку она не входит в стандарт ISO.
Ответ 2
Существует хорошее обсуждение об этом. P.J. Plauger отвечает на это
Я тот парень, который в 1983 году настаивал, что пространство имена, доступные для программы C, должны быть разделены на:
a) те, которые определены реализацией в интересах программиста (например, printf)
b) те, которые зарезервированы для программиста (например, foo)
c) зарезервированные для реализации (такие как _unlink)
Мы знали даже тогда, что "реализация" была слишком монолитной - часто более одного источника поставляет бит реализации - но это было лучшее, что мы могли сделать в то время. Стандартный С++ ввел пространства имен, чтобы помочь, но они достигли только часть их заявленных целей. (Что происходит, когда вы стандартизировать бумажного тигра.)
В этом конкретном случае Posix поставляет список категорий (a) имен (например, unlink), которые вы должны определить, когда и только когда вы включают определенные заголовки. Поскольку C-стандарт украл свои заголовки из Unix, который является тем же источником, что и для Posix, некоторые из этих заголовков исторически перекрываются. Тем не менее, предупреждения компилятора должны иметь каким-то образом учитывать, поддерживает ли поддерживаемая среда "чистый" стандарт С++ (платоновский идеал) или смешанный C/С++/Posix Окружающая среда. Нынешняя попытка Microsoft помочь нам программисты не учитывают это. Он настаивает на лечении unlink как имя категории (b), которое является близоруким.
Ну, GCC не будет объявлять имена POSIX в строгом режиме C, по крайней мере (хотя он все еще работает в режиме С++):
#include <stdio.h>
int main() {
&fdopen;
return 0;
}
Вывод с использованием -std=c99
test.c: In function 'main':
test.c:4: error: 'fdopen' undeclared (first use in this function)
Вам нужно будет прямо сказать, что вы работаете в смешанном C/Posix, используя макросы проверки функций или не передавая какой-либо конкретный стандарт. Затем он будет по умолчанию равен gnu89
, который предполагает смешанную среду (man feature_test_macros
). По-видимому, MSVC не имеет такой возможности.
Ответ 3
Как уже отмечалось, getcwd не включен в ISO С++, но является частью POSIX/IEEE Std 1003.1.
Microsoft решила включить некоторые из наиболее часто используемых функций POSIX в свою стандартную библиотеку C (но префикс этих функций подчеркивает, чтобы по существу препятствовать их использованию).
Ответ 4
Насколько я знаю, getcwd() никогда не был частью стандарта ISO С++. _getcwd() определенно нет, поскольку стандартные имена не начинаются с подчеркивания.
Фактически, статья MSDN ссылается на man-страницу, в которой говорится, что она объявлена в direct.h, которая не является заголовочным файлом Standard С++. Статья кажется мне фиктивной.
Ответ 5
Чтобы добавить к сообщению Dan Olson: См. Страница соответствия ANSI C на MSDN
Имена функций и глобальных переменных, специфичных для Microsoft, начинаются с одного символа подчеркивания. Эти имена могут быть переопределены только локально, в пределах вашего кода. Например, когда вы включаете файлы заголовков времени выполнения Microsoft, вы все равно можете локально переопределить определенную Microsoft функцию с именем _open, объявив локальную переменную с тем же именем. Однако вы не можете использовать это имя для своей собственной глобальной функции или глобальной переменной.
Ответ 6
Статья MSDN несколько путается в том, что нормальный человек мог бы сделать из просто быстрого чтения (если они не читают его с очень осторожным глазом адвоката).
Что говорится в статье MSDN: getcwd() не соответствует стандарту ISO С++. Чтобы соответствовать этому стандарту ISO С++ для именования функций (что является нарушением getcwd), Microsoft правильно помещает _ на фронт функции, поэтому одна и та же функция становится _getcwd(). Это ISO-совместимый способ именования функции, потому что getcwd() и _getcwd() не являются стандартной функцией стандарта ISO С++, а специфичной для Microsoft (поставщика) или специфичной для реализации функцией.
В статье не указывается, что стандартный вызов С++ ISO для получения рабочего каталога будет... хотя это то, что люди, как правило, читают с быстрым взглядом.
Ответ 7
Для записи getcwd()
не был устаревшим по ISO. Microsoft "устарела". Microsoft переписала множество функций C - часто с учетом немного лучшей безопасности (скажем, строковых функций, которые также принимают параметр max_length
). Затем они компилировали эти предупреждения, которые я считаю фиктивными, потому что ни одна из групп стандартов не осуждала какую-либо из функций, объявленных устаревшими.