Гость
Форумы / C++ [игнор отключен] [закрыт для гостей] / преобразование массива к unsigned long / 18 сообщений из 18, страница 1 из 1
02.05.2021, 23:01
    #40067994
andron81
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
преобразование массива к unsigned long
Добрый вечер.

А может кто-нибудь пояснить , что физически представляет собой преобразование массива из байтов в unsigned long ?

Код: plaintext
1.
2.
3.
4.
unsigned char pool[3];
    for (int i = 0; i < 3; i++)
        pool[i] = 0;
    unsigned long X = (unsigned long)pool;



в результате X = 2030976 почему получается это число ???
...
Рейтинг: 0 / 0
02.05.2021, 23:06
    #40067996
petrav
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
преобразование массива к unsigned long
andron81,

Это не преобразование массива. Это преобразование адреса массива к unsigned long. Т.е. в unsigned long сохранился адрес массива в оперативной памяти. В данном случае адрес массива равен адресу нулевого элемента этого массива.
...
Рейтинг: 0 / 0
02.05.2021, 23:12
    #40068000
andron81
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
преобразование массива к unsigned long
petrav
andron81,

Это не преобразование массива. Это преобразование адреса массива к unsigned long. Т.е. в unsigned long сохранился адрес массива в оперативной памяти. В данном случае адрес массива равен адресу нулевого элемента этого массива.


спасибо.
...
Рейтинг: 0 / 0
02.05.2021, 23:19
    #40068002
andron81
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
преобразование массива к unsigned long
petrav
andron81,

Это не преобразование массива. Это преобразование адреса массива к unsigned long.


точно, pool ведь содержит адрес первого элемента массива. тупанул.
...
Рейтинг: 0 / 0
02.05.2021, 23:26
    #40068003
petrav
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
преобразование массива к unsigned long
andron81
petrav
andron81,

Это не преобразование массива. Это преобразование адреса массива к unsigned long.


точно, pool ведь содержит адрес первого элемента массива. тупанул.

Нулевого элемента массива. И нет такой переменной pool, которая содержала бы адрес чего-то.
...
Рейтинг: 0 / 0
03.05.2021, 11:13
    #40068030
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
преобразование массива к unsigned long
andron81,

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

Код: plaintext
1.
2.
3.
4.
5.
6.
unsigned char pool[sizeof(long)] = {...};

long l;
memcpy(&l, pool, sizeof(l)); // OK

l = *(long*)pool; // UB
...
Рейтинг: 0 / 0
03.05.2021, 13:16
    #40068054
andron81
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
преобразование массива к unsigned long
Anatoly Moskovsky
andron81,

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

Код: plaintext
1.
2.
3.
4.
5.
6.
unsigned char pool[sizeof(long)] = {...};

long l;
memcpy(&l, pool, sizeof(l)); // OK

l = *(long*)pool; // UB



ого. да я смотрю вообще все эти преобразования это надо 20 раз подумать прежде чем делать. я почему спрашиваю в книге Эккеля разбирается перегрузка new и delete для классов. очень подробно разжовывать эккель не любит что делает в своих примера поэтому приходится догадываться. в общем как я понимаю он тут велосипедит new при помощи массива и держит массив с состоянием занят/не занят блок . а потом делает delete и вычисляет координату блока и помечает её как свободная. так вот там как раз это преобразование. Вы хотите сказать, что тут UB в delete ?


Код: plaintext
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.
61.
62.
63.
64.
65.
#include <cstddef> // Size_t
#include <fstream>
#include <iostream>
#include <new>
using namespace std;
ofstream out("Framis.out");

class Framis {
    enum { sz = 10 };
    char c[sz]; // To take up space, not used
    static unsigned char pool[];
    static bool alloc_map[];
public:
    enum { psize = 100 };  // frami allowed
    Framis() { out << "Framis()\n"; }
    ~Framis() { out << "~Framis() ... "; }
    void* operator new(size_t u) throw(bad_alloc);
    void operator delete(void*);
};
unsigned char Framis::pool[psize * sizeof(Framis)];
bool Framis::alloc_map[psize] = { false };

// Size is ignored -- assume a Framis object
void*
Framis::operator new(size_t u) throw(bad_alloc) {
    for (int i = 0; i < psize; i++)
        if (!alloc_map[i]) {
            out << "using block " << i << " ... ";
            alloc_map[i] = true; // Mark it used
            return pool + (i * sizeof(Framis));
        }
    out << "out of memory" << endl;
    throw bad_alloc();
}

void Framis::operator delete(void* m) {
    if (!m) return; // Check for null pointer
    // Assume it was created in the pool
    // Calculate which block number it is:
    unsigned long block = (unsigned long)m
        - (unsigned long)pool;
    block /= sizeof(Framis);
    out << "freeing block " << block << endl;
    // Mark it free:
    alloc_map[block] = false;
}

int main() {
    Framis* f[Framis::psize];
    try {
        for (int i = 0; i < Framis::psize; i++)
            f[i] = new Framis;
        new Framis; // Out of memory
    }
    catch (bad_alloc) {
        cerr << "Out of memory!" << endl;
    }
    delete f[10];
    f[10] = 0;
    // Use released memory:
    Framis* x = new Framis;
    delete x;
    for (int j = 0; j < Framis::psize; j++)
        delete f[j]; // Delete f[10] OK
} ///:~
...
Рейтинг: 0 / 0
03.05.2021, 13:19
    #40068055
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
преобразование массива к unsigned long
Anatoly Moskovsky
единственный способ это сделать без UB это memcpy()

А как же union ?
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
union {
  unsigned char pool[sizeof(long)];
  long l;
} pl;

for(size_t i = 0; i != sizeof(long); i++) p.pool[i] = 0;
printf("%u\n", pl.l);
...
Рейтинг: 0 / 0
03.05.2021, 13:22
    #40068057
petrav
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
преобразование массива к unsigned long
Dima T
Anatoly Moskovsky
единственный способ это сделать без UB это memcpy()

А как же union ?
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
union {
  unsigned char pool[sizeof(long)];
  long l;
} pl;

for(size_t i = 0; i != sizeof(long); i++) p.pool[i] = 0;
printf("%u\n", pl.l);


Там тоже UB, как я понимаю. С++ такой язык — что не сделай UB. И выход один: пиши свой класс строк, потому что все этим занимаются.
...
Рейтинг: 0 / 0
03.05.2021, 13:27
    #40068061
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
преобразование массива к unsigned long
petrav
Там тоже UB, как я понимаю. С++ такой язык — что не сделай UB.

memcpy(), union и прочие вышеописанные попытки подменить один тип данных другим это не совсем UB, но работает только для POD типов .
...
Рейтинг: 0 / 0
03.05.2021, 13:29
    #40068063
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
преобразование массива к unsigned long
Dima TА как же union ?

Это UB в С++, но нормально в С. Поэтому компиляторы обычно молча применяют С-поведение,
даже если исходник на С++.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
03.05.2021, 13:44
    #40068069
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
преобразование массива к unsigned long
Dima T
А как же union ?

Если можно pool обернуть в union, то да. Но не всегда возможно.
petrav
Там тоже UB, как я понимаю.

Нет. С union нет UB если массив байтов содержит валидный объект который trivially-copyable (как в данном примере).

Dima T
memcpy(), union и прочие вышеописанные попытки подменить один тип данных другим это не совсем UB, но работает только для POD типов.

Для не POD по-моему должно быть и так очевидно, что создавать объект побайтно нельзя.
А для POD основная проблема которую решают memcpy и union это выравнивание.
Есть платформы где нельзя в произвольном месте читать long и прочие типы. Поэтому UB если char* приводится к long* и разыменовывается, если там не было объекта такого типа.

Но например так можно даже и для не POD:
Код: plaintext
1.
2.
3.
std::string s;
char* p = (char*)&s;
*(std::string*)p = "xxx"; // можно потому что известно что p указывает на объект типа std::string
...
Рейтинг: 0 / 0
03.05.2021, 13:54
    #40068073
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
преобразование массива к unsigned long
Anatoly MoskovskyС union нет UB если массив байтов содержит валидный объект который trivially-copyable (как
в данном примере).

Это они одумались только в 14-м стандарте.
https://en.cppreference.com/w/cpp/language/union
The details of that allocation are implementation-defined but all non-static data
members will have the same address (since C++14). It's undefined behavior to read from the
member of the union that wasn't most recently written. Many compilers implement, as a
non-standard language extension, the ability to read inactive members of a union.

Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
03.05.2021, 14:59
    #40068099
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
преобразование массива к unsigned long
Dimitry Sibiryakov
Это они одумались только в 14-м стандарте.

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

А вот reinterpret_cast (и c-cast) реально на некоторых платформах не работают.
...
Рейтинг: 0 / 0
04.05.2021, 10:39
    #40068268
a guest
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
преобразование массива к unsigned long
Anatoly Moskovsky
Для справки, если у вас есть массив байтов которые вы хотите рассматривать как другой тип, то единственный способ это сделать без UB это memcpy()
Единственный способ это std::bit_cast, а memcpy между объектами разных типов это UB.
...
Рейтинг: 0 / 0
04.05.2021, 10:43
    #40068269
a guest
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
преобразование массива к unsigned long
Anatoly Moskovsky
Для не POD по-моему должно быть и так очевидно, что создавать объект побайтно нельзя.
Что такое "создавать объекты побайтно"?
...
Рейтинг: 0 / 0
04.05.2021, 11:28
    #40068281
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
преобразование массива к unsigned long
a guest
Единственный способ это std::bit_cast, а memcpy между объектами разных типов это UB.

Нет.
...
Рейтинг: 0 / 0
04.05.2021, 13:31
    #40068320
a guest
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
преобразование массива к unsigned long
Anatoly Moskovsky
a guest
Единственный способ это std::bit_cast, а memcpy между объектами разных типов это UB.

Нет.
Ок, UB между объектами разных типов, за исключением описанного в http://eel.is/c draft/basic.types.general#2
...
Рейтинг: 0 / 0
Форумы / C++ [игнор отключен] [закрыт для гостей] / преобразование массива к unsigned long / 18 сообщений из 18, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]