Каков тип переменной errno в C++?

Я занимался системным программированием на 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, принимает целое число в качестве аргумента. мой вопрос

  1. Если это тип int, почему он не работает в приведенном выше коде?
  2. Если нет, то какой это тип?

person user123456    schedule 28.11.2017    source источник
comment
Даже самый поверхностный поиск показывает, что errno — это макрос препроцессора, используемый для...   -  person 2785528    schedule 28.11.2017


Ответы (2)


errno – это определяемый реализацией макрос, который расширяется до выражения типа int.

Проблема в том, что вы используете имя errno в качестве аргумента функции, что недопустимо. Поскольку имя errno является макросом, оно расширяется. Для меня это приводит к std::string errorString(int (*_errno())). Ваш фрагмент работает нормально, если вы измените имя аргумента.

std::string errorString(int error_num){
    return std::strerror(error_num);
}
person François Andrieux    schedule 28.11.2017

В дополнение к ответу Франсуа давайте посмотрим, что выдает препроцессор в системе 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 впереди, это также будет допустимым объявлением параметра.

Ура макросам.

person Thomas    schedule 28.11.2017
comment
С нетерпением жду этого, и htons и все остальные макросы будут заменены! - person UKMonkey; 28.11.2017