Каждое использование толстой кишки ( ":" ) в C

Мне интересен каждый контекст, в котором двоеточие (символ ":" ) является допустимым синтаксическим элементом (вне литерала строки/символа, комментария и т.д.) в программе C.

Я попробовал поиск спецификации C99, но ":" соответствует каждой отдельной странице, а "двоеточие" не находит каждого использования. Точно так же, просматривая игру "C парсеры (и я понимаю, что lex/yacc не способны разбора C) Я только вижу частичные результаты.

Это сценарии, которые, как я знаю, используют двоеточие:

  • Условный оператор
  • Бит-поле
  • Наклейки

Существуют ли какие-либо другие языковые функции в C, которые используют двоеточие?

Ответ 1

Стандарт C (N1570) определяет орграфы:

6.4.6 Пунктуаторы
....

3   во всех аспектах языка шесть жетонов

        <: :> <% %> %: %:%:

  ведут себя соответственно так же, как шесть токенов 79)

        [ ] { } # ##

за исключением их правописания. 80)


79) Эти жетоны иногда называют "орграфами".

80) Таким образом, [ и <: ведут себя по-разному, когда "строятся" (см. 6.10.3.2), но в противном случае могут свободно меняться.

В качестве дополнительной заметки стандарт С++ уточняет термин:

Термин "орграф" (токен, состоящий из двух символов) не является отлично описательный, поскольку один из альтернативных токенов предварительной обработки %:%: и, конечно, несколько основных токенов содержат два персонажи. Тем не менее, эти альтернативные маркеры, которые не содержат лексических ключевых слов, обычно называются "орграфами".

Согласно Диграфы и триграфы:

В 1994 году нормативная поправка к стандарту C, включенная в C99, предоставила орграфы в качестве более читаемых альтернатив пяти из триграмм.....

В отличие от триграфов, орграфы обрабатываются во время токенизации, и любой орграф должен всегда представлять полный токен сам по себе или компоновать токен %:%:, заменяющий токен конкатенации препроцессора ##. Если в другом токене происходит последовательность орграфа, например, строка с кавычками или символьная константа, она не будет заменена.

Ответ 2

Поиск грамматики C99 Приложение A...

знаки пунктуации

Уже покрывается @AlexD.

условное выражение (aka trernary)

logical-OR-expression ? expression : conditional-expression

struct-declarator (aka struct bit-fields)

declarator[optional] : constant-expression

labeled-statement (чаще всего используется в операторах switch)

identifier : statement
case constant-expression : statement
default : statement

И что это.

Ответ 3

В дополнение к уже упомянутым случаям символ : может легально появляться (ссылки на проект N1570 C11, синтаксис в 6.10p1):

  • h- char -последовательность директивы a #include:
    #include <foo:bar.h>
    (6.10.2p2)

  • q- char -последовательность директивы a #include или #line:
    #include "foo:bar.h"
    Это не синтаксически строковый литерал (6.10.2p3)

  • Список заметок макроопределения:
    #define COLON :

  • Не директива (которая, несмотря на имя, на самом деле является препроцессорной директивой:
    # :
    Да, я считаю, что это действительно так, хотя gcc и clang отвергают его.

  • A #error:
    #error foo : bar

  • A #pragma директива: #pragma foo : bar

Ни один из них, скорее всего, не встречается в реальном коде (хотя я полагаю, что директива #include для кода, относящегося к Windows, может ссылаться на "C:\dir\blah.h").

Ответ 4

Поскольку тегом является , а не, например, , я встречал еще не упомянутый в использовании ответов в расширении GNU C asm extended:

С расширенным asm вы можете читать и писать переменные C из ассемблера и выполнить переходы от ассемблерного кода до меток C. Расширенный синтаксис asm использует двоеточия (:) для разделения параметров операнда после шаблон ассемблера:

 asm [volatile] ( AssemblerTemplate
                  : OutputOperands
                  [ : InputOperands
                  [ : Clobbers ] ])

 asm [volatile] goto ( AssemblerTemplate
                       :
                       : InputOperands
                       : Clobbers
                       : GotoLabels)

Ключевое слово asm является расширением GNU. При написании кода, который можно скомпилировать с помощью -ansi и различных опций -std, используйте __asm__ вместо asm.