Я занимался системным программированием на C ++ и хочу передать переменную errno в системах linux моему обработчику исключений. Вы можете увидеть пример кода здесь
https://pastebin.com/ppgMc8Hj
#include <sys/stat.h>
#include <cerrno>
#include <iostream>
#include <cstring>
std::string errorString(int errno){
return std::strerror(errno);
}
int main(){
struct stat sb;
errno = 0;
if(stat("/jdfj/", &sb)){
errorString(errno);
}
else{
std::cout << std::boolalpha << S_ISDIR(sb.st_mode) << std::endl;
}
}
Но это возвращает ошибку, как это
In function 'int main()':
14:26: error: invalid conversion from 'int' to 'int* (*)()' [-fpermissive]
6:13: note: initializing argument 1 of 'std::string errorString(int* (*)())'.
Я видел здесь http://en.cppreference.com/w/cpp/string/byte/strerror что стандартная функция, которая возвращает строку из errno, принимает в качестве аргумента int.
Мой вопрос
errno
макрос, определяемый реализацией, который расширяется до выражения типа int
,
Проблема в том, что вы используете имя errno
в качестве аргумента вашей функции, что недопустимо. Поскольку имя errno
это макрос, он расширен Для меня это приводит к std::string errorString(int (*_errno()))
, Ваш фрагмент отлично работает, если вы измените имя аргумента.
std::string errorString(int error_num){
return std::strerror(error_num);
}
В дополнение к ответу Франсуа, давайте посмотрим, что выводит препроцессор в системе Linux с GCC. g++ -E test.cpp
дает:
# 6 "test.cpp"std::string errorString(int
# 6 "test.cpp" 3 4
(*__errno_location ())
# 6 "test.cpp"){
return std::strerror(
# 7 "test.cpp" 3 4
(*__errno_location ())
# 7 "test.cpp");
}
Так errno
определяется как (*__errno_location ())
Вот. Это на самом деле вызов функции, но если вы положите int
впереди, это также является объявлением допустимого параметра.
Yay для макросов.