Зачем использовать внешнюю букву «C» вокруг пространства имен C

#c #c #gcc

#c #c #gcc

Вопрос:

Несколько дней назад я наткнулся на этот фрагмент кода C , хотя я не могу вставить сам код, я мог бы воссоздать проблему с помощью некоторого примера кода. Во-первых, файл namespace.h:

 #include <iostream>
using namespace std;

namespace useless{
  class X {
     int m_myint;
     static X *m_foobar;
     X* getPrivVal(void);
  public:
     int getMember(void);
     X* getStaticVal(void);
  };
}
  

Далее, namespace.cpp :

 #include "namespace.h"

extern "C"{
   namespace useless{
     X* X::m_foobar = NULL;
     X* X::getPrivVal(void){
         if(m_foobar == NULL)
             m_foobar = new X;
         return(m_foobar);
     }
   }
}

namespace useless {
   int X::getMember(void){
       if(m_myint == 0)
           m_myint = 1;
      return(m_myint);
   }
   X* X::getStaticVal(void){
        return(getPrivVal());
   }
}

using namespace useless;

int main(void){
    X y;
    cout << "The int value is " << y.getMember() << endl;
    cout << "The value of the static member is " << y.getStaticVal() << endl;
    return(0);
}
  

Этот код отлично компилировался и связывался, когда я использовал g 3.4.3, но выдает следующую ошибку, когда я использую g 4.x, я пробовал с GCC 4.6.1, а также GCC 4.2.1. Пробовал это как на Linux, так и на Mac, те же результаты.

Это ошибка (Suse):

 g   -o namespace namespace.cpp
namespace.h:8:15: error: previous declaration of useless::X* 
    useless::X::m_foobar with C   linkage
namespace.cpp:5:11: error: conflicts with new declaration with C linkage
  

Может ли кто-нибудь, пожалуйста, пролить некоторый свет на то, что хотел сделать устаревший код C , могло ли это быть взломом или обходным путем, чтобы обойти старую проблему, о которой я больше не знаю. Кстати, метод внутри extern "C" вызывается кодом C , а не каким-либо кодом C, как я изначально подозревал.
К вашему сведению, сейчас это устаревший код, возможно, он был написан в 2001/2002 годах.


Спасибо, ребята. Я пошел дальше и избавился от внешнего «C» без каких-либо серьезных последствий. @Бьорн Поллекс : Парень, который написал этот код, давно ушел.

Комментарии:

1. Если этот код контролируется версиями, проверьте историю, чтобы найти того, кто это написал, и бейте их палкой, пока они не покаются в своих грехах.

Ответ №1:

extern "C" Директива имеет два эффекта: она отключает искажение, когда это возможно, и использует соглашение о вызовах C. В данном конкретном случае, поскольку между ними существует пространство имен, искажение имен нельзя отключить, поэтому его можно было бы добавить для принудительного выполнения определенного соглашения о вызовах.

Код на самом деле неверен в том смысле, что объявление не выполняет принудительное extern "C" действие, а определение выполняет, что неверно. Учтите, что если компилятор просто следовал директиве, как показано, вызывающий объект будет использовать соглашения об именовании и вызовах C , в то время как функция будет использовать вариант C, если они отличаются, результатом будет неопределенное поведение.

Ответ №2:

Похоже на попытку сгенерировать переменные без искажения имен C . Это одна из частей использования extern "C" .

Новый компилятор, очевидно, понимает, что это действительно не работает.

Ответ №3:

Если у вас есть фрагмент кода C , который вы хотите вызвать из модуля, написанного на другом языке (C, FORTRAN или любом другом), вы хотите отключить искажение имен C .

Редактировать: действительно странно то, что они сделали это в определении, но не в объявлении. Удивительно, что он когда-либо компилировался

Комментарии:

1. Отключение искажения имен не имеет смысла, когда вы говорите об эксклюзивных функциях C , таких как классы и пространства имен.