Как включить динамический массив ВНУТРИ структуры в C?

Чтобы слишком сильно сфокусироваться на этом дробном узоре (в качестве индикатора внутренних деталей хэша), может быть запутанным. Существует один аспект «скалярного значения» хеша, который важен для потенциально каждой программы Perl, и если это считается истинным в булевом контексте , см. Пример:

if (%h) {
    print "Entries in hash:\n";
    for my $k (sort keys %h) {
        print "$k: $h{$k}\n";
    }
}

В perldoc perldata, раздел Scalar-values ​​, вы можете прочитать, что

[...] Булевский контекст - это просто особый вид скаляра контекст, в котором когда-либо не выполняется преобразование в строку или число.

blockquote>

и некоторые абзацы позже

Если вы оцениваете хэш в скалярном контексте, он возвращает false, если хэш пуст. Если есть пары ключей / значений, он возвращает true [...]

blockquote>

42
задан Ciro Santilli 新疆改造中心996ICU六四事件 4 May 2016 в 15:46
поделиться

7 ответов

То, как вы его написали сейчас, называются «взломом структурирования», пока C99 - до «C99» как «гибкий элемент массива». Причина, по которой вы получаете ошибку (возможно, в любом случае), это то, что она должна сопровождаться запятой:

#include <stdlib.h>

struct my_struct {
    int n;
    char s[];
};

, когда вы выделяете пространство для этого, вы хотите выделить размер структуры Plus Количество пространства, которое вы хотите для массива:

struct my_struct *s = malloc(sizeof(struct my_struct) + 50);

В этом случае гибкий элемент массива представляет собой массив CHAR и SIZEOF (CHAR) == 1, поэтому вам не нужно умножить по его размеру, но так же Любой другой Malloc, который вам нужно, если бы это был массив некоторых других типов:

struct dyn_array { 
    int size;
    int data[];
};

struct dyn_array* my_array = malloc(sizeof(struct dyn_array) + 100 * sizeof(int));

Редактирование: Это дает другой результат от изменения элемента на указатель. В этом случае вы (как правило) нуждаются в двух отдельных распределениях, один для самого структуры, и один для «дополнительных» данных, которые необходимо указывать на указатель. Используя гибкий элемент массива, вы можете выделить все данные в одном блоке.

71
ответ дан 26 November 2019 в 21:13
поделиться

Вы должны решить, что вы пытаетесь сделать в первую очередь.


Если вы хотите иметь структуру с указателем на AS [Независимый] массив внутри, вы должны объявить его как

struct my_struct { 
  int n; 
  char *s;
}; 

в этом случае, вы можете создать фактический объект Struct Crust, как угодно, пожалуйста (как автоматическую переменную Например)

struct my_struct ms;

и затем выделите память для массива независимо

ms.s = malloc(50 * sizeof *ms.s);  

на самом деле, нет общего необходимости выделить память массива динамически

struct my_struct ms;
char s[50];

ms.s = s;

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

Обратите внимание, что в этом случае у вас есть две независимые блоки памяти: структура и массив.


Совершенно другой подход будет использоваться идиома «stack Hack». В этом случае массив становится неотъемлемой частью структуры. Оба проживают в одном блоке памяти. В C99 структура будет объявлена ​​как

struct my_struct { 
  int n; 
  char s[];
}; 

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

struct my_struct *ms = malloc(sizeof *ms + 50 * sizeof *ms->s);

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

Обратите внимание, что в этом случае у вас нет возможности создавать такие структурные объекты как статические или автоматические объекты. Структы с гибкими элементами массива в конце могут быть выделены только динамически в C.


Ваше предположение о aritmics aritmectics, чем быстрее, а затем массивы абсолютно неверны. Массивы работают через указатель арифметики по определению, поэтому они в основном одинаковы. Более того, подлинный массив (не разлагается до указателя), как правило, немного быстрее, чем объект указателя. Значение указателя должно быть прочитано из памяти, в то время как местоположение массива в памяти является «известным» (или «рассчитанным») из самого объекта массива.

20
ответ дан 26 November 2019 в 21:13
поделиться

Указатель арифметика быстрее, чем массивы, да?

Не совсем - они на самом деле одинаковы. Массивы переводят на указатель арифметики при компиляции времени.

char test[100];
test[40] = 12;

// translates to: (test now indicates the starting address of the array)
*(test+40) = 12;
0
ответ дан 26 November 2019 в 21:13
поделиться

использование массива неуказанного размера только позволяется в конце структуры и только работает в некоторых компиляторах. Это - нестандартное расширение компилятора. (Хотя я думаю, что помню, что C++ 0x будет позволять это.)

массив не будет отдельным выделением для от структуры все же. Таким образом, необходимо выделить все из my_struct, не только часть массива.

то, Что я делаю, просто дают массиву небольшой, но ненулевой размер. Обычно 4 для символьных массивов и 2, чтобы массивы wchar_t сохранили выравнивание на 32 бита.

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

кроме того, я думаю, что вы не должны использовать sizeof (символ*) в вашем выделении.

Это - то, что я сделал бы.

struct my_struct {
    int nAllocated;
    char s[4]; // waste 32 bits to guarantee alignment and room for a null-terminator
};

int main()
{
    struct my_struct * pms;
    int cb = sizeof(*pms) + sizeof(pms->s[0])*50;
    pms = (struct my_struct*) malloc(cb);
    pms->nAllocated = (cb - sizoef(*pms) + sizeof(pms->s)) / sizeof(pms->s[0]);
}
1
ответ дан 26 November 2019 в 21:13
поделиться

Массивы будут решать указателям, и здесь вы должны определить s как CHAR * S . Конструкция в основном является контейнером, и должен (IIRC) быть фиксированным размером, поэтому наличие динамично размером массива внутри него просто невозможно. Поскольку вы MALLOC в любом случае память, это не должно иметь никакого значения в том, что вы после.

В основном вы говорите, S будет указывать местоположение памяти. Обратите внимание, что вы все еще можете получить доступ к этому позже, используя нотацию, подобную S [0] .

0
ответ дан 26 November 2019 в 21:13
поделиться

Я должен заявить, что, хотя нет нового релиза каждые 2 месяца, как Роб заявил, что вы можете иногда испытывать это чувство. Хотя есть еще действие на гугл-группу и гитуб. Если что-то до Рождества было больше свежих лиц, начинающих вносить вклады, чем раньше (даже простые, такие как doco), это показывает мне, что может быть больше интереса, чем когда-либо, его просто то, что люди получают с этим.

Моя работа использует Subsonic (как 2.2, так и 3.0.0.3) в большинстве проектов, где мы контролируем его. У нас есть около 28 .net devs, и они все любят это (мы не попадаемся в то, что он не может сделать, как его не ORM/доступ к данным говорят per se.

Поскольку мы используем только Donsonic для низкоуровневого инструмента запроса, а не в качестве уровня доступа к данным, я полагаю, что мы не слишком тесно связаны с ним, если нам нужно заложить его, но у нас еще есть причина.

Моя точка зрения такова: Его действительно действительно легко использовать, легко подобрать, легко модифицировать, легкий инструмент запроса/ORM (в меньшей степени). Есть немного инструментов, которые имеют все эти свойства и, тем не менее, не запирают вас в миллион школ мысли о вещах. Из-за этого я не вижу, что он умирает в ближайшее время - это слишком привыкание инструмент, чтобы иметь на ремне летучей мыши.

Я активный фанатский буй звукозаписи и SubSonic Rocksorz My Sockorz!

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

-121--3085452-

Пытались ли вы настроить команду - Q в качестве ускорителя в меню? Можете ли вы заставить ваше приложение ответить на него?

Я не положительный, но я думаю, что это работает в Linux и, вероятно, Windows с эквивалентным Alt - F4 . Мое приложение отвечает на «убойный» нажатие клавиши, я обрабатываю некоторый код очистки, а затем делаю программный System.exit () .

Если вы «просто» после изящной обработки выхода, вы можете также захотеть поймать WindowEvent WINDOW _ CLOSING , где традиционно «вы уверены?» все делается.

-121--1576009-

Я подозреваю, что компилятор не знает, сколько места ему потребуется выделить для s [], если вы решите объявить с ним автоматическую переменную.

Я согласен с тем, что сказал Бен, объявите вашу структуру

struct my_struct {
    int n;
    char s[1];
};

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

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

0
ответ дан 26 November 2019 в 21:13
поделиться

, сгенерированный код, будет идентичен (массив и PTR). Помимо того, что массив один не скомпилируется, это

и BTW - сделайте его C ++ и использовать вектор

-6
ответ дан 26 November 2019 в 21:13
поделиться
Другие вопросы по тегам:

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