Эта ошибка также возникает на Android 8+, когда вызывается Service.startForeground (int id, уведомление уведомления) , а id - 0.
id int : Идентификатор этого уведомления в соответствии с NotificationManager.notify (int, Notification); не должно быть 0.
Поведение <fcntl.h>
и <unistd.h>
в C ++ не указано стандартом (поскольку они также не являются частью стандарта C89). Тем не менее, я никогда не видел платформу, где они (а) существуют, и (б) на самом деле нужно обернуть в блок extern "C"
.
Поведение <stdio.h>
, <math.h>
и другие стандартные заголовки C указаны в разделе D.5 стандарта C ++ 03. Они не требуют блока оболочки extern "C"
, и они выгружают свои символы в глобальное пространство имен. Однако все, что содержится в приложении D, «устарело».
Каноническая форма C ++ этих заголовков - <cstdio>
, <cmath>
и т. Д., И они указаны в разделе 17.4.1.2 (3) of стандарт C ++, в котором говорится:
<cassert> <ciso646> <csetjmp> <cstdio> <ctime> <cctype> <climits>
<csignal> <cstdlib> <cwchar> <cerrno> <clocale> <cstdarg> <cstring>
<cwctype>
За исключением случаев, указанных в статьях с 18 по 27, содержимое каждого заголовка cname должно быть таким же, как содержимое соответствующего заголовка name.h, as указанных в ISO / IEC 9899: 1990 Языки программирования C (раздел 7), или Языки программирования по ИСО / МЭК: 1990.-C ПОПРАВКА 1: C Целостность (пункт 7), если это необходимо, как бы включив. Однако в стандартной библиотеке C ++ декларации и определения (за исключением имен, которые определены как макросы в C) находятся в области пространства имен (3.3.5) пространства имен std.
blockquote>So стандартный, не устаревший, канонический способ использования (например)
printf
в C ++ -#include <cstdio>
, а затем вызываетstd::printf
.
Это является хорошей идеей, чтобы компилятор знал, чтобы он мог ожидать кода C при компиляции как C ++. Вы также можете обнаружить, что сами файлы заголовков содержат extern "C" {
в качестве охранников.
Например, curses.h
в моей системе содержит:
#ifdef __cplusplus
extern "C" {
...
extern "C"
делает. Это не меняет интерпретацию кода. Это даже не относится к коду. Это директива языковой привязки, которая инструктирует компилятор генерировать символы, совместимые с теми, которые линкер ожидает для C. Он делает код C ++ вызываемым из C, но не меняет генерацию кода.
– IInspectable
7 September 2016 в 08:50
extern "C"
. Директива применяется только для обозначения имен символов. Он не имеет отношения к вызовам.
– IInspectable
14 April 2017 в 17:56
Да, да. Однако многие системы (особенно Linux) уже добавляют брекетинг extern "C"
, как и вы. Файлы /usr/include/unistd.h
/usr/include/features.h
и макроса __BEGIN_DECLS
, определенные в /usr/include/sys/cdefs.h
и используемые во многих системах Linux, содержат файлы /usr/include/unistd.h
/usr/include/features.h
.
Итак, в Linux вы обычно можете избежать extern "C"
, но это не наносит вреда (и, IMHO, улучшает читаемость в этом случае).
Нет, вы должны использовать заголовки обертки C ++ (например, как <cstdio>
). Те, кто заботится обо всем этом для вас.
Если это заголовок, который не имеет этих, то да, вы захотите обернуть их в extern "C" {}
.
ETA : Стоит отметить, что многие реализации будут включать оболочку внутри файла .h, как показано ниже, так что вы можете уйти, не выполняя ее самостоятельно.
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
<cstdio>
и т. Д. Технически помещают свои определения в пространство имен std
. (Многие реализации также помещают их в пространство имен верхнего уровня, но это не то, что говорит стандарт).
– Nemo
11 November 2011 в 01:14
Заголовки системы C обычно уже включают блок extern "C"
, защищенный #ifdef __cplusplus
. Таким образом, функции автоматически объявляются как extern "C"
при компиляции C ++, и вам не нужно делать это вручную.
Например, в моей системе unistd.h
и fcntl.h
начинаются с __BEGIN_DECLS
и заканчиваются на __END_DECLS
, которые являются макросами, определенными в sys/cdefs.h
:
/* C++ needs to know that types and declarations are C, not C++. */
#ifdef __cplusplus
# define __BEGIN_DECLS extern "C" {
# define __END_DECLS }
#else
# define __BEGIN_DECLS
# define __END_DECLS
#endif
Я просто дважды проверил stdlib.h для компилятора GNU и объявления не использовали extern «C» в качестве деклараций.
edit:
if defined __cplusplus && defined _GLIBCPP_USE_NAMESPACES
define __BEGIN_NAMESPACE_STD namespace std {
Итак, в том числе старые заголовки будут размещать объявления на std при условии, что _GLIBCPP_USE_NAMESPACES определен?