Слэш и точки в именах функций и прототипах?

Я новичок в C и смотрю Go исходное дерево. Я нашел это:

https://code.google.com/p/go/source/browse/src/pkg/runtime/race.c

void runtime∕race·Read(int32 goid, void *addr, void *pc);
void runtime∕race·Write(int32 goid, void *addr, void *pc);

void
runtime·raceinit(void)
{
    // ...
}

Что означают черты и точки (·)? Действительно ли это C?

Ответ 1

ВАЖНОЕ ОБНОВЛЕНИЕ:

Конечный ответ, безусловно, тот, который вы получили от Russ Cox, один из авторов Go, в списке рассылки golang-nuts. Тем не менее, я оставляю некоторые из моих предыдущих заметок ниже, они могут помочь понять некоторые вещи.

Кроме того, прочитав этот ответ, приведенный выше, я считаю, что псевдо-slash теперь может быть переведен на обычный / слэш (например, middot переводится в точку) в более новые версии компилятора Go C чем тот, который я тестировал ниже, но у меня нет времени проверять.


Файл скомпилирован Внутренний компилятор языка Go Language Suite, который происходит в компиляторе Plan 9 C (1) (2) и имеет некоторые отличия (в основном расширения, AFAIK) до стандарта C.

Один из расширений состоит в том, что он позволяет символам UTF-8 в идентификаторах.

Теперь, в компиляторе Go Language Suite C, символ middot (·) обрабатывается особым образом, поскольку он преобразуется в обычную точку (.) в объектных файлах, которая интерпретируется внутренним компоновщиком языка Go Language Suite как символ разделителя пространства имен.

Пример

Для следующего файла example.c (обратите внимание: он должен быть сохранен как UTF-8 без спецификации):

void ·Bar1() {}
void foo·bar2() {}
void foo∕baz·bar3() {}

внутренний компилятор C создает следующие символы:

$ go tool 8c example.c
$ go tool nm example.8
 T "".Bar1
 T foo.bar2
 T foo∕baz.bar3

Теперь, пожалуйста, обратите внимание, что я дал ·Bar1() капитал B. Это потому что таким образом я могу сделать его видимым для обычного кода Go - потому что он переводится на тот же самый символ, который компиляция следующего кода Go:

package example
func Bar1() {}  // nm will show:  T "".Bar1

Теперь, в отношении функций, которые вы назвали в вопросе, история идет дальше по кроличьей дыре. Я немного менее уверен, что я здесь, но я попытаюсь объяснить на основе того, что знаю. Таким образом, каждое предложение ниже этого пункта следует читать так, как будто оно было "AFAIK ", написанное только в конце.

Итак, следующая недостающая часть, необходимая для того, чтобы лучше понять эту загадку, заключается в том, чтобы узнать что-то еще о странном пространстве имен "" и о том, как обрабатывается компоновщик Go suite. Пространство имен "" - это то, что мы можем назвать "пустым" (потому что "" для программиста означает "пустая строка" ), или, может быть, лучше, "пространство имен". И когда компоновщик видит импорт следующим образом:

import examp "path/to/package/example"
//...
func main() {
    examp.Bar1()
}

то он принимает файл библиотеки $GOPATH/pkg/.../example.a, а во время фазы импорта заменяет "на лету" каждый "" с помощью path/to/package/example. Итак, теперь в связанной программе мы увидим такой символ:

 T path/to/package/example.Bar1

Ответ 2

Символ "·" \xB7 соответствует моей консоли Javascript. Символ "/" - \x2215.

Точка находится в приложении D C99 standard содержит списки специальных символов, которые являются действительными в качестве идентификаторов в C. Слэш не кажется, поэтому я подозреваю, что он использовался как что-то еще (возможно, пространство имен) с помощью магии #define или препроцессора.

Это объясняет, почему точка присутствует в определении фактической функции, но косой чертой нет.

Изменить: Отметьте Этот ответ для получения дополнительной информации. Возможно, что косой чертой unicode просто разрешена реализация GCC.

Ответ 3

Похоже, что это не стандарт C, ни C99. В частности, он gcc и clang жалуется на точку, даже в режиме C99.

Этот исходный код компилируется комплектом компиляторов Part 9 (в частности,. /pkg/tool/darwin _amd64/6c в OS X), который загружается системой сборки Go. Согласно этот документ, внизу страницы 8, Plan 9 и его компилятор вообще не используют ASCII, но вместо этого используют Unicode. Внизу страницы 9 указано, что любой символ с достаточно высокой точкой кода считается действительным для использования в имени идентификатора.

Никакой магии предварительной обработки вообще - определение функций не соответствует объявлению функций просто потому, что это разные функции. Например, void runtime∕race·Initialize(); - это внешняя функция, определение которой содержится в. /src/pkg/runtime/race/race.go; аналогично для void runtime∕race·MapShadow(…).

Функция, которая появляется позже, void runtime·raceinit(void), является совершенно другой функцией, которая является aparant по тому, что она фактически вызывает runtime∕race·Initialize();.

Ответ 4

Компилятор go/runtime компилируется с использованием компиляторов C, первоначально разработанных для plan9. Когда вы строите переход от источника, сначала создадите компиляторы plan9, а затем используйте их для сборки Go.

Компиляторы plan9 поддерживают имена функций Unicode [1], а разработчики Go используют символы Unicode в своих именах функций как псевдопространства.

[1] Похоже, что это может быть действительно совместимо со стандартами: имя переменной unixode g++, но gcc не поддерживает имена функций/переменных unicode.