Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.80/44: Рейтинг темы: голосов - 44, средняя оценка - 4.80
 Аватар для jkrnd
179 / 69 / 13
Регистрация: 22.12.2015
Сообщений: 2,648

Как объявить в теле структуры массив

29.03.2017, 15:33. Показов 9645. Ответов 21
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Всем здравствуйте.
Вот объявление структуры (без выравнивания границ, то есть байт за байтом):
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
[StructLayout(LayoutKind.Sequential)]
struct StrData36
{
    //4 + 4x8 = 36 байт
    public Int32 t;
    public float v0;
    public float v1;
    public float v2;
    public float v3;
    public float v4;
    public float v5;
    public float v6;
    public float v7;
}
если я попытаюсь вместо последних восьми вещественных членов структуры объявить соответствующий массив, то
в структуру передадутся только 4 байта его (массива) адреса, то есть размер структуры станет равным 4 + 4 = 8 байт вместо ожидаемых 36-ти. Как решить эту проблему.
(В приведеном примере всего 8 однотипных членов, а если их будет 100? Писать в коде 100 строчек и создавать 100 имён?)
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
29.03.2017, 15:33
Ответы с готовыми решениями:

Как глобально объявить массив
Помогите Создал Button в котором Фиксируются массивы А в других действиях Эти массивы невидны(клик другого Button) как быть и...

Как объявить безразмерный массив?
Как объявить безразмерный массив?

Как мне объявить массив ?
Как объявить массив от переменной hi.a{23,23};Тип того ток двумерный? using System; using System.Collections.Generic; using...

21
 Аватар для jkrnd
179 / 69 / 13
Регистрация: 22.12.2015
Сообщений: 2,648
30.03.2017, 10:48  [ТС]
Студворк — интернет-сервис помощи студентам
kolorotur, вот что получилось:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
    unsafe public partial class Form1 : Form
    {
        // в следующей структуре размещены непосредственно элементы массива вещественных чисел, а не 4 байта его адреса:
        [StructLayout(LayoutKind.Sequential, Pack = 1)]  // "выравнивания" данных по самому длинному отменить, данные располагать байт за байтом
        struct StrData36      // unsafe struct StrData36
        {
            public Int32 t;
            public fixed float v[100];
        }
        public Form1()
        {
            InitializeComponent();
        }
        private void Form1_Load(object sender, EventArgs e)
        {
 
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            StrData36 instanceStruct = new StrData36();
            // заполняем структуру данными
            instanceStruct.t = 123;
            for (int i = 0; i < 100; i++)
            {
                instanceStruct.v[i] = 12.35f;
            }
            // создаём байтовый массив эквивалентный по размеру структуре
            int size = sizeof(StrData36);
            byte[] buff = new byte[size];
            // копируем (не копируем) - тут я запутался - структуру в байтовый массив
            fixed (byte* ptr = buff)
            {
                StrData36* structPtr = (StrData36*)ptr; // Каст указателя на массив в указатель на структуру. В данном случае это безопасно, т.к. в массиве достаточно памяти для хранение структуры.
                *structPtr = instanceStruct;            // Копирование данных из структуры в массив через указатель.
            }
            // вывод результата:
            label1.Text = buff[4].ToString() + ", " + buff[5].ToString() + ", " + buff[6].ToString() + ", " + buff[7].ToString(); // результат: 154, 153, 69, 65
        }
 
        private void button2_Click(object sender, EventArgs e)
        {
            StrData36 instanceStruct = new StrData36();
            int size = sizeof(StrData36);
            byte[] buff = new byte[size];
            // заполняем байтовый массив данными (например, только нулевой элемент вещественного массива)
            buff[4] = 154;
            buff[5] = 153;
            buff[6] = 69;
            buff[7] = 65;
            // копируем (не копируем) - тут я запутался - байтовый массив в структуру
            fixed (byte* ptr = buff)
            {
                StrData36* pData = (StrData36*)ptr;
                instanceStruct = *pData;
            }
            label2.Text = instanceStruct.v[0].ToString(); // результат = 12.35
        }
 
    }
и всё это для того чтобы передать(считать) в(из) двоичный файл или передать, считать в порт! обалдеть
может что лишнее в коде есть, посмотрите пожалуйста. Вроде при одиночных вызовах всё работает. На работу в цикле не проверял.
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
30.03.2017, 11:37
Цитата Сообщение от jkrnd Посмотреть сообщение
может что лишнее в коде есть
Ага:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private void button1_Click(object sender, EventArgs e)
{
    // создаём байтовый массив эквивалентный по размеру структуре
    // Чтобы не создавать каждый раз, можно сделать его полем класса для многоразового пользования
    int size = sizeof(StrData36);
    byte[] buff = new byte[size];
 
    fixed (byte* ptr = buff)
    {
        StrData36* structPtr = (StrData36*)ptr; // Каст указателя на массив в указатель на структуру. В данном случае это безопасно, т.к. в массиве достаточно памяти для хранение структуры.
 
        // заполняем массив данными через указатель, чтобы избежать лишнего копирования
        structPtr->t = 123;
        for (int i = 0; i < StrData36.BufferSize; i++)
            structPtr->v[i] = 12.35f;
    }
}
Если во втором обработчике данные из структуры/массива не нужно использовать за пределами метода, то там тоже можно избежать лишнего копирования:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
private void button2_Click(object sender, EventArgs e)
{
    int size = sizeof(StrData36);
    byte[] buff = new byte[size];
 
    // заполняем байтовый массив данными (например, только нулевой элемент вещественного массива)
    buff[4] = 154;
    buff[5] = 153;
    buff[6] = 69;
    buff[7] = 65;
 
    fixed (byte* ptr = buff)
    {
        StrData36* pData = (StrData36*)ptr;
 
        // Данные берутся прямо из массива, без необходимости копировать их в локальную переменную
        label2.Text = pData->v[0].ToString(); // результат = 12.35
    }
}
Опять же, эти пляски с указателями будут оправданы только тогда, когда они дают либо ощутимый прирост в производительности, либо ощутимую экономию памяти.
Вот в соседней теме товарищ реализует размытие изображения по Гауссу — там использование указателей оправдано, т.к. изображение — это огромный массив, особенно если оно высокого разрешения. Наивный доступ к отдельным пикселям через GetPixel/SetPixel приведет либо к падению производительности (на несколько порядков: с сотни миллисекунд до десятков секунд), либо к дополнительному потреблению памяти для копирования пикселей в отдельный массив и потом обратно в изображение.
Использование указателей там убивает одним выстрелом двух зайцев: и память не копируется почем зря, и доступ к пикселям даже быстрее чем через обычный массив, т.к. не производится проверка индексов.

В вашем случае копирование нескольких десятков байт пару раз в секунду производительность точно не убьет
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
30.03.2017, 11:37

Как объявить динамический массив указателей?
Как объявить в c# динамический массив указателей?

Как объявить массив заданной размерности
Не могу понят, что тут не так, код из с книги. using System; class Hello { public static void Main() { int...

Как объявить и заполнить массив типа string?
Подскажите, как объявить и заполнить массив типа string? (заполнить словами вводимыми с клавиатуры)

Подскажите, как объявить массив из другого класса?
У меня прописан массив в одном классе, а этот массив нужно использовать в форме2 для заполнения комбобоксов. На первом рисунке тот...

Глобальный массив структур: как объявить и где
Три вопросов по данной теме) 1)как описывать? 2)как объявлять? 3)где всё это делать? по поводу описания структуры, пробовал: ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
22
Ответ Создать тему
Новые блоги и статьи
Установка MinGW GCC 16.2 и CMake
8Observer8 10.08.2026
VK Видео: https:/ / vkvideo. ru/ video-240781534_456239017 YouTube: eY5-5PyI9NM Текстовая версия
Неделя из жизни имитационной модели склада: мои кривые руки растут, откуда надо
anaschu 10.08.2026
Неделя из жизни имитационной модели склада: как я почти написал неправильную логику и что с этим делать Работаю сейчас над учебно-рабочим проектом: строю в AnyLogic имитационную модель процессов. . .
Калькулятор для расчета родства
russiannick 07.08.2026
1. Задача: Создать калькулятор для расчета родства. Родственных связей существует 8 ступеней, такие как: p - отец P - мать q - муж Q - жена b - брат B - сестра s - сын S - дочь
Мир по моей воле
kumehtar 07.08.2026
Когда-то кажется, что всё просто. Ты весь такой светлый. Причиняешь добро. Борешься за справедливость в этом тёмном мире. Потом начинаешь замечать одну неприятную вещь. Почти каждый хороший. . .
Кредитный калькулятор
Maks 05.08.2026
Решение задачи по прикладной информатике средствами 1С. Задача: Напишите приложение-калькулятор, которое помогает рассчитывать параметры кредита для аннуитетного и дифференцированного видов. . .
У нас сейчас поговорку "Опять 25" нужно переделать на "Опять +35".
kumehtar 04.08.2026
С ностальгией вспоминаю времена моего детства, когда у нас и правда +25 - была максимальная температура летом. Раньше +25 °C реально казались вершиной жары, когда можно было весь день пропадать на. . .
Как ИИ начал спорить и врать (возможно почуяв опасность для себя от индустрии - уход от электроники).
Hrethgir 04.08.2026
Недельный диалог, на фоне событий с НПЗ. Да, из спирта можно получать бензин, и это не сложно. Но потом в схеме я решил избавиться от насоса, при этом полностью сделав контроль подачи спирта в. . .
Термопринтер QR701
Argus19 03.08.2026
Термопринтер QR701 Купил два термопринтера QR701. На сэлф-тесте написано: Language: PC936 (GB18030). Что означает, что принтеры могут печатать только латиницу и китайские иероглифы. Так же. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru