Как работает инициализация динамического квадратного квадрата в C? [Дубликат]

Есть 5 6 NINE (или 63 *, в зависимости от того, как вы рассчитываете) разные способы записи многострочных строк в YAML.

Блокировать скалярные стили (>, |)

Они позволяют использовать символы, такие как \ и " без экранирования, и добавить новую строку (\n) в конец строки

> Сложенный стиль удаляет одиночные строки новой строки внутри строки (но добавляет один в конец и преобразует двойные строки в синглы):

Key: >
  this is my very very very
  long string

this is my very very very long string\n

| Литеральный стиль превращает каждую новую строку внутри строки в литеральную новую строку, и добавляет один в конец:

Key: |
  this is my very very very 
  long string

this is my very very very\nlong string\n

Вот официальное определение из YAML Spec 1.2

Скалярное содержимое может быть записано в блок-нотации, используя литеральный стиль (обозначается символом «|»), где все разрывы строк значительны. В качестве альтернативы, они могут быть записаны со сложенным стилем (обозначается символом «>»), где каждый разрыв строки складывается в пространство, если только он не заканчивается пустой или более с отступом.

Блок >-, |+)

Вы можете управлять обработкой последней новой строки в строке и любыми простыми пустыми строками (\n\n), добавив символ индикатора блокировки блока :

  • >, |: «clip»: сохранить линию, удалить завершающие пустые строки .
  • >-, |-: «strip»: удалить линию, удалить завершающие пустые строки.
  • >+, |+: «сохранить»:

Скалярные стили «Поток» (, ", ')

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

простой стиль (без экранирования, нет # или :, ограничения на первый символ):

Key: this is my very very very 
  long string

стиль с двойными кавычками (\ и " должен быть экранирован \, строки новой строки могут быть вставлены с буквальной последовательностью \n, строки могут быть объединены без пробелов с конечным \):

Key: "this is my very very \"very\" loooo\
  ng string.\n\nLove, YAML."

& rarr; "this is my very very \"very\" loooong string.\n\nLove, YAML."

стиль с одним кадром (буквальный ' должен быть удвоен, никаких специальных символов, возможно полезно для выражения строк, начинающихся с двойных кавычек ):

Key: 'this is my very very "very"
  long string, isn''t it.'

& rarr; "this is my very very \"very\" long string, isn't it."

Резюме

В этой таблице _ означает space character. \n означает «символ новой строки» (\n в JavaScript), за исключением строки «строки строки», где это означает буквально обратную косую черту и n).

                      >     |            "     '     >-     >+     |-     |+
-------------------------|------|-----|-----|-----|------|------|------|------  
Trailing spaces   | Kept | Kept |     |     |     | Kept | Kept | Kept | Kept
Single newline => | _    | \n   | _   | _   | _   | _    |  _   | \n   | \n
Double newline => | \n   | \n\n | \n  | \n  | \n  | \n   |  \n  | \n\n | \n\n
Final newline  => | \n   | \n   |     |     |     |      |  \n  |      | \n
Final dbl nl's => |      |      |     |     |     |      | Kept |      | Kept  
In-line newlines  | No   | No   | No  | \n  | No  | No   | No   | No   | No
Spaceless newlines| No   | No   | No  | \   | No  | No   | No   | No   | No 
Single quote      | '    | '    | '   | '   | ''  | '    | '    | '    | '
Double quote      | "    | "    | "   | \"  | "   | "    | "    | "    | "
Backslash         | \    | \    | \   | \\  | \   | \    | \    | \    | \
" #", ": "        | Ok   | Ok   | No  | Ok  | Ok  | Ok   | Ok   | Ok   | Ok
Can start on same | No   | No   | Yes | Yes | Yes | No   | No   | No   | No
line as key       |

Примеры

Обратите внимание на конечные пробелы в строке перед «пробелами».

- >
  very "long"
  'string' with

  paragraph gap, \n and        
  spaces.
- | 
  very "long"
  'string' with

  paragraph gap, \n and        
  spaces.
- very "long"
  'string' with

  paragraph gap, \n and        
  spaces.
- "very \"long\"
  'string' with

  paragraph gap, \n and        
  s\
  p\
  a\
  c\
  e\
  s."
- 'very "long"
  ''string'' with

  paragraph gap, \n and        
  spaces.'
- >- 
  very "long"
  'string' with

  paragraph gap, \n and        
  spaces.

[
  "very \"long\" 'string' with\nparagraph gap, \\n and         spaces.\n", 
  "very \"long\"\n'string' with\n\nparagraph gap, \\n and        \nspaces.\n", 
  "very \"long\" 'string' with\nparagraph gap, \\n and spaces.", 
  "very \"long\" 'string' with\nparagraph gap, \n and spaces.", 
  "very \"long\" 'string' with\nparagraph gap, \\n and spaces.", 
  "very \"long\" 'string' with\nparagraph gap, \\n and         spaces."
]

Стили блоков с индикаторами отступа

На всякий случай выше для вас недостаточно, вы можете добавить «индикатор отступа блока » (после индикатора блокировки блока, если он у вас есть):

- >8
        My long string
        starts over here
- |+1
 This one
 starts here

Добавление

Если вы вставляете лишние пробелы в начале не-первых строк в стиле Folded, они будут сохранены с бонусной новой линией. Это не происходит с стилями потока:

- >
    my long
      string
- my long
    string

["my long\n string\n", "my long string"]

Я даже не могу.

* 2 (или нет) и с 9 возможными индикаторами отступов (или none), 1 простой стиль и 2 кавычки: 2 x (2 + 1) x (9 + 1) + 1 + 2 = 63

Часть этой информации также была обобщена здесь .

1
задан Jonathan Leffler 3 July 2015 в 06:19
поделиться

4 ответа

  • Случай 1: В
     char Buffer[MAX_BUF];
    
    Buffer представлен массив размера MAX_BUF. Техника выделения называется VLA .
  • Случай 2: В
    const int MAX_BUF = 1000;
    char* Buffer = malloc(MAX_BUF);
    
    Buffer указатель , которому выделена память размера MAX_BUF, которая является 1000.

и массив не совпадает с указателем, а C-FAQ имеет очень хорошую коллекцию, в которой подробно описаны причины .

Основное различие в терминах удобство и поведение:

  1. (1) находится в стеке, обычно Примечание, в то время как (2) всегда находится в куче.
  2. (1) имеет фиксированный размер после выделения , (2) может быть изменена.
  3. (1) выделяется при вызове функции-оболочки и имеет область OTOH блока, (2) распределяется память динамически, во время выполнения и возвращенная память имеет срок службы который простирается от выделения до освобождения.
  4. (1) выделенная память не должна управляться программистом, а в (2) все malloc() d памяти должны быть free() d. [Courtesy: Giorgi ]

Примечание: Wiki

Например, Компилятор GNU C выделяет память для VLA в стеке.

2
ответ дан Community 21 August 2018 в 04:07
поделиться
char* Buffer = malloc(MAX_BUF);

создает указатель char Buffer, динамически выделяет MAX_BUF байты памяти через malloc и делает Buffer точкой для начала выделенного пространства. Эта память выделяется в куче.

char Buffer[MAX_BUF];

создает массив Buffer размера MAX_BUF, который может содержать максимум символов MAX_BUF. Обратите внимание, что вы создаете массив переменной длины (функция, введенная в C99 ), поскольку MAX_BUF является переменной. Этот массив может быть создан в стеке.

2
ответ дан Cool Guy 21 August 2018 в 04:07
поделиться
  • 1
    Обратите внимание, что технически массив представляет собой VLA (массив переменной длины), потому что MAX_BUF не является константой времени компиляции. – Jonathan Leffler 3 July 2015 в 06:20
  • 2
    Благодарю. Я пропустил это. – Cool Guy 3 July 2015 в 06:36

Я добавлю немного информации с точки зрения управления памятью, в дополнение к тому, что говорили другие.

1) Основное различие здесь:

const int MAX_BUF = 1000;
char* Buffer = malloc(MAX_BUF);

Вам нужно управлять выделенной памятью вручную, например, free Buffer, когда вы закончите с ней.

2) Во втором случае:

char Buffer[MAX_BUF];

Вам ничего не нужно, чтобы освободить его (или освободить его дважды). Он будет автоматически уничтожен. Следовательно, вы избегаете задачи обработки памяти - это хорошо. Вы должны стараться всегда оценивать, какой подход вам нужен.

Некоторые точки.

  • Поскольку вторая выделена в стеке, первый подход берется также при создании большого массива - поскольку больше памяти обычно доступно в куче .
  • Также, если вы создаете массив с использованием второго подхода, например, в методе, это будет время жизни объекта - вы не сможете использовать этот массив вне этого метода. В то время как с динамическим распределением это не так.
2
ответ дан Giorgi Moniava 21 August 2018 в 04:07
поделиться
  • 1
    Ницца. Требуется угол free(), который и я, и @coolguy пропустили. :-) – Sourav Ghosh 3 July 2015 в 06:42
  • 2
    Я добавил, что с атрибутами. :-) – Sourav Ghosh 3 July 2015 в 06:48
  • 3
    @SouravGhosh: Понятно, хорошо. – Giorgi Moniava 3 July 2015 в 07:00

Наиболее заметным отличием является область. Массив VLA будет действителен только внутри области, где он объявлен, тогда как динамический массив будет доступен везде в программе до тех пор, пока вы не назовете free().

На практике VLA может быть быстрее, чем динамическая память , если компилятор использует распределение стека для VLA. Однако он не указывается стандартом C, где выделен VLA.

(Компилятор мог теоретически распределить VLA в куче, но тогда компилятор также будет отвечать за очистку. Я не думаю, что такие решения существуют. Каждый компилятор, который я использовал всегда объявлять VLA в стеке.)

Это означает, что VLA не подходят для хранения больших объемов данных: вы рискуете переполнением стека. Однако это не проблема, когда вы используете динамическую память.

VLAs не имеют такой же переносимости, как и динамические массивы, поскольку ужасно старые компиляторы не поддерживают VLA. Теоретически, новым компиляторам C11 также не нужно поддерживать VLA, хотя на данный момент я знаю, что никакой компилятор не был настолько глуп, чтобы отказаться от этой поддержки.


Сравнение / сводка:

  • VLAs следует использовать, когда имеется небольшое количество локальных данных, поскольку они имеют быстрое время распределения и автоматическую очистку.
  • Динамические массивы должны использоваться, когда есть большие объемы данных, чтобы предотвратить переполнение стека.
  • Динамические массивы должны использоваться, когда данные должны сохраняться после выполнения функции и быть доступный в другом месте программы.
  • Динамические массивы должны использоваться, когда у вас есть исключительные и / или иррациональные требования к переносимости.
0
ответ дан Lundin 21 August 2018 в 04:07
поделиться
Другие вопросы по тегам:

Похожие вопросы: