У меня есть код, который счастливо скомпилирован с g ++ версии 3. что-то. Затем я захотел создать какой-то другой код, содержащий символы C ++ 11, поэтому я обновился до g ++ 4.7. Теперь мой оригинальный код не собирается. Я получаю ошибку:
‘fdopen’ не был объявлен в этой области
Согласно man-странице, fdopen () объявлен в stdio.h, который я включаю. Я не уверен, что это актуально, но я работаю в среде Cygwin. Точной версией g ++, которую я использую, является версия 4.7.2, предоставленная Cygwin.
Я не изменил этот код, так как я переключил компилятор, и я могу точно подтвердить, что он собран, и мой тестовый код выполнялся и проходил с предыдущим компилятором.
В соответствии с просьбой, пример кода для демонстрации проблемы:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc, char **argv)
{
int fd;
FILE *fp;
fd = open("test.txt", (O_WRONLY | O_CREAT | O_EXCL), S_IRWXU);
if(0 < fd)
{
fp = fdopen(fd, "wb");
fprintf(fp, "Testing...\n");
fclose(fp);
}
return 0;
}# g++ -std=c++11 -o test test.cpp
test.cpp: In function 'int main(int, char**)':
test.cpp:14:29: error: 'fdopen' was not declared in this scope
Проблема исходит от -std=c++11
, fdopen()
функция не в ANSI C (только в стандарте POSIX), а компилируется с -std=c++11
опция подразумевает определение __STRICT_ANSI__
, что исключает несколько функций из stdio.h
, Кстати, в программах на C ++ обычно следует включать <cstdio>
вместо <stdio.h>
, посмотреть здесь: stdio.h не стандартно в C ++?.
Если вам нужно использовать fdopen()
вы можете удалить -std=c++11
вариант при компиляции. Другое возможное решение, хотя и не очень элегантное, может заключаться в использовании этого в вашем исходном коде:
#ifdef __STRICT_ANSI__
#undef __STRICT_ANSI__
#include <cstdio>
#define __STRICT_ANSI__
#else
#include <cstdio>
#endif
(который предназначен для работы с и без -std=c++11
опция).
Что бы вы ни делали, пожалуйста, не связывайтесь с __STRICT_ANSI__
флаг. Этот символ контролируется GCC. Вы должны позволить GCC определить это и оставить это в покое.
То, что вы действительно ищете, это _POSIX_C_SOURCE
функциональный тестовый макрос. Ты видишь, fdopen
не определяется стандартом языка C. Когда вы говорите GCC, что вы пишете программу на C ++ 11, GCC переходит в «строгий» режим, где он пытается не определять функции, которые не определены языком. Это сделано для того, чтобы избежать конфликтов имен с вашим собственным кодом. Например, действительная программа на C ++ 11 может свободно определять свою собственную функцию с именем fdopen
поскольку fdopen
не является зарезервированным идентификатором в языке.
Но fdopen
является определяется POSIX, который является стандартом, который включает, но отдельно от стандарта языка C. При написании приложения, которое использует функции POSIX, например fdopen
, вы должны сообщить системе, что вы собираетесь написать приложение POSIX чтобы он знал, что должен сделать функции, определенные POSIX, доступными для вашей программы. Это где _POSIX_C_SOURCE
вступает макрос функционального теста. В верхней части каждого исходного файла перед включением любого заголовка задайте для этого макроса соответствующее значение. Например:
#define _POSIX_C_SOURCE 200112L
Значение, которое вы должны использовать в определении, зависит от того, на какую версию POSIX вы нацелены. Если вы не уверены, на какую версию вы хотите установить таргетинг, вы можете просто указать ту же версию, с которой ваша хост-система совместима. Вы можете определить это, запустив getconf
из скорлупы:
$ getconf _POSIX_VERSION
200809L
$ _
Здесь моя система говорит мне, что она совместима с версией POSIX 200809L
(т.е. POSIX.1-2008). Я могу #define _POSIX_C_SOURCE 200809L
в моем исходном коде и будьте уверены, что все стандартные функции, поддерживаемые моей системой, будут мне доступны.