powered by simpleCommunicator - 2.0.48     © 2025 Programmizd 02
Форумы / C++ [игнор отключен] [закрыт для гостей] / преобразование массива к unsigned long
18 сообщений из 18, страница 1 из 1
преобразование массива к unsigned long
    #40067994
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Добрый вечер.

А может кто-нибудь пояснить , что физически представляет собой преобразование массива из байтов в 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
преобразование массива к unsigned long
    #40067996
petrav
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andron81,

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

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


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

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


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

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


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

Нулевого элемента массива. И нет такой переменной pool, которая содержала бы адрес чего-то.
...
Рейтинг: 0 / 0
преобразование массива к unsigned long
    #40068030
Фотография 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
...
Рейтинг: 0 / 0
преобразование массива к unsigned long
    #40068054
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
преобразование массива к unsigned long
    #40068055
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);
...
Рейтинг: 0 / 0
преобразование массива к unsigned long
    #40068057
petrav
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
преобразование массива к unsigned long
    #40068061
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
petrav
Там тоже UB, как я понимаю. С++ такой язык — что не сделай UB.

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

Это UB в С++, но нормально в С. Поэтому компиляторы обычно молча применяют С-поведение,
даже если исходник на С++.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
преобразование массива к unsigned long
    #40068069
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
преобразование массива к unsigned long
    #40068073
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
преобразование массива к unsigned long
    #40068099
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov
Это они одумались только в 14-м стандарте.

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

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

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

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


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