Ошибка «fdopen» не была объявлена ​​» найдено с g ++ 4, скомпилированным с g ++ 3

У меня есть код, который счастливо скомпилирован с 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

5

Решение

Проблема исходит от -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 опция).

3

Другие решения

Что бы вы ни делали, пожалуйста, не связывайтесь с __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 в моем исходном коде и будьте уверены, что все стандартные функции, поддерживаемые моей системой, будут мне доступны.

8

По вопросам рекламы [email protected]