В Powershell, как я могу преобразовать строку с запаздывающим 'знаком' к числу?

Так что является обычной практикой определять параметр метода struct reclamation как указатель на const struct, чтобы мы могли избежать приведения к неконстантному в любое время и выполнить это грязное приведение один раз в реализации метода reclamation?

blockquote>

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

Вы отмечаете только const вещи, которые не собираетесь изменять; и освобождение его или данных, на которые ссылаются его члены, является изменением. Просто посмотрите, как объявлено free() : void free(void *), а не void free(const void *).

Это основная проблема в коде OP, и использование struct test_struct_t *test_struct_ptr = create(10); без квалификатора const является правильным решением.


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

Как правильно вернуть struct?

blockquote>

Давайте рассмотрим реальный случай: динамически размещаемый строковый буфер. Есть два основных подхода:

typedef struct {
    size_t          size;  /* Number of chars allocated for data */
    size_t          used;  /* Number of chars in data */
    unsigned char  *data;
} sbuffer1;
#define  SBUFFER1_INITIALIZER  { 0, 0, NULL }

typedef struct {
    size_t          size;  /* Number of chars allocated for data */
    size_t          used;  /* Number of chars in data */
    unsigned char   data[];
} sbuffer2;

Можно объявить и инициализировать первую версию с помощью макроса инициализатора препроцессора:

    sbuffer1  my1 = SBUFFER1_INITIALIZER;

Это используется, например, в. POSIX.1 pthread_mutex_t мьютексы и pthread_cond_t условные переменные.

Однако, поскольку второй имеет элемент гибкого массива, он не может быть объявлен статически; Вы можете только объявить указатели на него. Итак, вам нужна функция конструктора:

sbuffer2 *sbuffer2_init(const size_t  initial_size)
{
    sbuffer2  *sb;

    sb = malloc(sizeof (sbuffer2) + initial_size);
    if (!sb)
        return NULL; /* Out of memory */

    sb->size = initial_size;
    sb->used = 0;
    return sb;
}

, которую вы используете следующим образом:

    sbuffer2 *my2 = sbuffer2_init(0);

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

    sbuffer2 *my2 = NULL;
[ 1147] как эквивалент sbuffer1 my1 = SBUFFER1_INITIALIZER;.

Функция, которая может увеличивать или уменьшать объем памяти, выделенной для данных, нуждается только в указателе на первую структуру; но либо указатель на указатель на вторую структуру, либо возвращаемый возможно измененный указатель, чтобы изменения были видны вызывающей стороне.

Например, если мы хотим установить содержимое буфера из какого-либо источника, возможно,

int  sbuffer1_set(sbuffer1 *sb, const char *const source, const size_t length);

int  sbuffer2_set(sbuffer2 **sb, const char *const source, const size_t length);

Функции, которые только получают доступ к данным, но не изменяют их, также различаются:

int  sbuffer1_copy(sbuffer1 *dst, const sbuffer1 *src);

int  sbuffer2_copy(sbuffer2 **dst, const sbuffer2 *src);
[1151 ] Обратите внимание, что const sbuffer2 *src не является опечаткой. Поскольку функция не будет изменять указатель src (мы могли бы сделать его const sbuffer2 *const src!), Ей не нужен указатель на указатель на данные, только указатель на данные.

Действительно интересной частью являются функции возврата / освобождения.

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

void sbuffer1_free(sbuffer1 *sb)
{
    free(sb->data);
    sb->size = 0;
    sb->used = 0;
    sb->data = NULL;
}

Вторая сложная задача , Если мы будем следовать приведенной выше логике, мы напишем функцию восстановления / освобождения от отравления как

void sbuffer2_free1(sbuffer2 **sb)
{
    free(*sb);
    *sb = NULL;
}

, но поскольку программисты привыкли к шаблону void *v = malloc(10); free(v); (в отличие от free(&v);!), Они обычно ожидают вместо этого должна быть

void sbuffer2_free2(sbuffer2 *sb)
{
    free(sb);
}

; и этот не может отравить указатель. Если пользователь не выполнит эквивалент sbuffer2_free2(sb); sb = NULL;, существует риск повторного использования содержимого sb впоследствии.

Библиотеки C обычно не сразу возвращают память в ОС, а просто добавляют ее в свой собственный внутренний свободный список, чтобы использовать его при последующих вызовах malloc(), calloc() или realloc(). Это означает, что в большинстве ситуаций указатель может быть разыменован после free() без ошибки времени выполнения, но данные, на которые он указывает, будут чем-то совершенно другим. Это то, что делает эти ошибки настолько неприятными для воспроизведения и отладки.

Отравление просто устанавливает недопустимые значения для элементов структуры, так что использование после освобождения легко обнаруживается во время выполнения благодаря легко видимым значениям. Установка указателя, используемого для доступа к динамически распределенной памяти, на NULL означает, что если разыменовать указатель, программа должна завершиться с ошибкой сегментации . Это намного легче отладить с помощью отладчика; по крайней мере, вы можете легко найти точно, где и как произошла авария.

Это не так важно в автономном коде, но для библиотечного кода или кода, используемого другими программистами, это может повлиять на общее качество объединенного кода. Это зависит; Я всегда оцениваю это в каждом конкретном случае, хотя я склонен использовать версию-указатель-член-отравление для примеров.

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

6
задан halr9000 20 November 2008 в 21:11
поделиться

4 ответа

Править: согласно предложению Halr9000

$foo = "300-";
$bar = 0;
$numberStyles = [System.Globalization.NumberStyles];
$cultureInfo = [System.Globalization.CultureInfo];

[int]::TryParse($foo, $numberStyles::AllowTrailingSign, $cultureInfo::CurrentCulture, [ref]$bar);
5
ответ дан 16 December 2019 в 21:47
поделиться
[System.Globalization.NumberStyles]::AllowTrailingSign

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

"AllowTrailingSign"

Заключительное примечание, опрашивая Перечисление для всех возможных значений, использует строку:

[System.Globalization.NumberStyles] | gm -static
2
ответ дан 16 December 2019 в 21:47
поделиться

Вот лучший способ получить перечислимые значения:

$type = [System.Globalization.NumberStyles]
[enum]::GetValues($type)
1
ответ дан 16 December 2019 в 21:47
поделиться

Если Вы уверены, что знаки могли быть - или +, Строка. Замена могла помочь.

Если Вы подразумеваете, что 323-должен возвратиться-323, проверение на знак и умножение его-1 помогли бы.

0
ответ дан 16 December 2019 в 21:47
поделиться
Другие вопросы по тегам:

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