LINUX.ORG.RU

типы в c

 ,


1

3

есть такая структурка:

struct x { int i; ... char buf[4096 - ???]; };

проблема в размере buf. должно быть так:

static_assert(sizeof(struct x) == 4096);

как написать там нужный размер без боли? очевидный вариант не проходит:

struct x { int i; ... char buf[4096 - offsetof(struct x, buf)]; }; // struct x is incomplete
struct x { struct { int i; ... } y; char buf[4096 - sizeof(y)]; }; // y is undeclared
struct x { struct y { int i; ... } y; char buf[4096 - sizeof(struct y)]; }; //это работает, но как и в предыдущем случае нужно будет писать x.y.i вместо x.i

лучшее, что придумал:

struct x { union { struct { int i; ... char buf[]; }; char _[4096]; }; };

но хочется иметь простой sizeof(buf), а не костылями. есть ли способ?



Последнее исправление: jsforever (всего исправлений: 2)

Ответ на: комментарий от AntonI

типы в c (комментарий)

Внезапно - в Вашем примере buf тоже указатель, бгггг.

типы в c (комментарий)

То исть Вы не в курсе что сырые строки в С это char *?! Дяденька, учите матчасть.

повторять придётся долго, но уже себе.

jsforever
() автор топика
Ответ на: комментарий от AntonI

сколько раз мне это придется повторить что бы до Вас дошло?

Мне кажется, что его проблема в том, что он не пытается даже вникнуть в то, что ему пишут :)

u5er
()
Ответ на: комментарий от AntonI

Т.е. когда я написал

bool f(int *p) { return p[10]; }

я хоть и обратился к нему как к массиву, но уже будет просто арифметика указателей использоваться, а sizeof(p) даст мне просто размер указателя на инт? Хотя выглядит всё вполне пристойно?

AndreyKl ★★★★★
()
Последнее исправление: AndreyKl (всего исправлений: 1)
Ответ на: комментарий от jsforever

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

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

Я верю что к концу этого учебного года Вы сможете понять о чем шла речь! Главное не сдавайтесь!!

AntonI ★★★★★
()
Ответ на: комментарий от AndreyKl

Да. Причем Вы не знаете p[10] еще в массиве лежит или где то за его пределами. Если за пределами в лучшем случае будет сегфолт, в худшем UB и замучаетесь с отладкой.

Но если уверены что в p больше 10 элементов все нормально;-)

собственно std::array отчасти решает эти проблемы. Минус - задолбаешься в компайл тайм везде размеры массива протаскивать…

AntonI ★★★★★
()
Последнее исправление: AntonI (всего исправлений: 2)
Ответ на: комментарий от AndreyKl

я хоть и обратился к нему как к массиву

С чего вдруг такой поспешный вывод?
[] — это синтаксический сахарок для арифметики указателей, a[ b ] — это
*(a+b), если a — массив, b — целое
*(b+a), если b — массив, a — целое (угу можно и так: 10[ p ]).

PS. На самом деле как к массиву, но не из-за [], а из-за того что арифметика указателей вне массива — UB ;)

bormant ★★★★★
()
Последнее исправление: bormant (всего исправлений: 3)
Ответ на: комментарий от jsforever

На самом деле вы зря спорите.

buf будет ссылкой

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

Отсюда явно видно что вы просто не понимали что в питоне ссылки - это примерно то же что указатели в си. Или даже примерно то же что массивы в си. Массивы конечно хранят дополнительно размер (как мы тут выяснили, благодаря AntonI и bormant). Ну так вангую что и ссылки в питоне что то дополнительно хранят.

Вряд ли вы понимали эти детали когда утверждали что массивы в си и ссылки в питоне не одно и то же. По крайней мере по вашим примерам этого не очень видно. По крайней мере мне.

Мне кажется АнтонИ верно вам написал насчёт того что вы путаете способ хранения и способ обращения. Но это норм. Нужно обратить внимание и разобраться получше.

Успехов.

AndreyKl ★★★★★
()
Ответ на: комментарий от bormant

С чего вдруг такой поспешный вывод?

ну потому что он обратился к нему как к массиву;-)

Второй вариант b[a] меня вымораживает напрочь до сих пор, отцы-основатели были большими затейниками…

Но

int i[12], buf=2;
...
buf[i]

Это же какие возможности для обфускации кода!

AntonI ★★★★★
()
Последнее исправление: AntonI (всего исправлений: 1)
Ответ на: комментарий от AntonI

Да. Причем Вы не знаете p[10] еще в массиве лежит или где то за его пределами. Если за пределами в лучшем случае будет сегфолт, в худшем UB и замучаетесь с отладкой.

ну, всё не настолько плохо)

за пояснения спасибо, особенно за пример с протаскиванием массива.

собственно std::array отчасти решает эти проблемы. Минус - задолбаешься в компайл тайм везде размеры массива протаскивать…

Ну я просто вектор по ссылкам таскаю...

AndreyKl ★★★★★
()
Ответ на: комментарий от bormant

PS. На самом деле как к массиву, но не из-за [], а из-за того что арифметика указателей вне массива — UB ;)

а из-за того что арифметика указателей вне массива — UB

вот это совсем не распарсил..

Смутно вспоминаются манипуляции с полученным void* и вычислением смещения по известному размеру. Это что всё стыдноUB?

AndreyKl ★★★★★
()
Ответ на: комментарий от AntonI

buf

Это же какие возможности для обфускации кода!

кошмар сущий. любопытно какие были мотивы.. должна ж была быть польза от этого..

AndreyKl ★★★★★
()
Ответ на: комментарий от AntonI

ты что ранее рассказывал? - char[n] является char*, массив является указателем. т. е. о том, что никаких различий нет. далее ты загуглил и обнаружил различия между массивом и указателем, но чтобы отмазаться, начал говорить «это не та разница», «эта разница не считается». только не учёл, что в случае отношения «является» любая разница опровергает эквивалентность.

jsforever
() автор топика
Ответ на: комментарий от AndreyKl

Смутно вспоминаются манипуляции с полученным void* и вычислением смещения по известному размеру. Это что всё стыдноUB?

Как только вылезут за пределы object, так сразу и.

C23 (N3054)

6.5.6 Additive operators
8 For the purposes of these operators, a pointer to an object that is not an element of an array behaves the same as a pointer to the first element of an array of length one with the type of the object as its element type.
9 ... If the pointer operand and the result do not point to elements of the same array object or one past the last element of the array object, the behavior is undefined.

bormant ★★★★★
()
Ответ на: комментарий от AndreyKl

Отсюда явно видно что вы просто не понимали что в питоне ссылки - это примерно то же что указатели в си. Или даже примерно то же что массивы в си.

Или даже примерно то же что массивы в си.

указатель то же что массивы

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

Вряд ли вы понимали эти детали когда утверждали что массивы в си и ссылки в питоне не одно и то же

и снова то же самое.

Мне кажется АнтонИ верно вам написал насчёт того что вы путаете способ хранения и способ обращения

ну меня мало интересует, что там кажется эникею. с чего вдруг видения некомпетентного юнита стали аргументом?

jsforever
() автор топика
Ответ на: комментарий от jsforever

Вы пожалуйста держите при себе свои проекции. А то Вы себе что то придумали и как давай обижаться что реальность с Вашими фантазиями некоррелирует!

Когнитивные способности — это совокупность мозговых процессов, участвующих в познании окружающего мира. С их помощью человек воспринимает, обрабатывает, сортирует, запоминает, хранит и воспроизводит информацию. 

К когнитивным способностям относятся: 

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

Там пунктов много, у Вас с восприятием прям беда-беда.

AntonI ★★★★★
()
Ответ на: комментарий от AndreyKl

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

jsforever
() автор топика
Ответ на: комментарий от AndreyKl

Мне кажется АнтонИ верно вам написал насчёт того что вы путаете способ хранения и способ обращения.

Да. Точно кажется, и в части «верно», и в части «способов».

bormant ★★★★★
()
Ответ на: комментарий от bormant

Точно кажется, и в части «верно», и в части «способов».

поясните?

AndreyKl ★★★★★
()
Ответ на: комментарий от AntonI

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

ты иди объясняйся за вопросы, на которые ответить не смог. как так вышло?

jsforever
() автор топика

ТС, вот это что-ли хотел


#include <stdio.h>
#include <stdalign.h>

struct alignas(4096)  X{
    int i;
    float f;
};
int main()
{
    X arr[2];
    printf("arr size: %lu ", sizeof(arr));
    return 0;
}

arr size: 8192 

такое делается и без древних сишных грязнохаков

zurg
()
Ответ на: комментарий от zurg

ТС не знает чего хочет и это его страшно мучает.

Потому что для записи структуры куда нить с добиванием записи до 4К достаточно следить за позицией в потоке, до этого ТС наверное и сам бы мог допетрить.

AntonI ★★★★★
()
Ответ на: комментарий от bormant

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

zurg
()
Ответ на: комментарий от bormant

А что стандарт глаголет, точно все поля в начале лягут? И главное - buf перед f не может воткнуться? ЕМНИП у меня как то компилятор поменял поля местами.

AntonI ★★★★★
()
Ответ на: комментарий от AntonI

В структурах? Точно нет, иначе это ломало бы всё взаимодействие программ и библиотек.

u5er
()
Ответ на: комментарий от bormant

тоже не особо. предлагается делать sizeof(X) - offsetof(X, buf) вместо sizeof(buf)? подобное уже было в оп. чем мне это должно помочь?

jsforever
() автор топика
Ответ на: комментарий от AntonI

А почему Вы таки думаете что sizeof структуры всегда есть сумма sizeof-в ее частей?;-)

Я совершенно точно знаю, что это не так. Но… вы знаете способ лучше?

AndreyKl

а не поясните разницу между массивами и указателями в си, а то я запутался немного.

Главные отличия - массив хранит свой размер и он не может быть изменен.

char arr[10];
char *ptr;
sizeof(arr) == 10
sizeof(ptr) == 2, 4, 8, ???
arr = ptr; // ошибка
ptr = arr; // корректно

AntonI

Второй вариант b[a] меня вымораживает напрочь до сих пор, отцы-основатели были большими затейниками…

Хех. Развлекался так когда-то: https://www.cyberforum.ru/c-beginners/thread2082993.html#post11259966

bormant

А теперь?

error: expected identifier or ‘(’ before numeric constant
   21 | struct alignas(4096)  X{
COKPOWEHEU
()
Ответ на: комментарий от jsforever

чем мне это должно помочь?

Тем, что struct X — завершенное определение структуры, buf[] — последнее поле этой структуры, имеющее неполный тип, но это допустимо (flexible array member), sizeof struct X == 4096, размер buf[] константно вычислим сразу после завершения объявления типа.

6.7.2.1 Structure and union specifiers
20 As a special case, the last member of a structure with more than one named member may have an incomplete array type; this is called a flexible array member. In most situations, the flexible array member is ignored. In particular, the size of the structure is as if the flexible array member were omitted except that it may have more trailing padding than the omission would imply. However, when a . (or ->) operator has a left operand that is (a pointer to) a structure with a flexible array member and the right operand names that member, it behaves as if that member were replaced with the longest array (with the same element type) that would not make the structure larger than the object being accessed; the offset of the array shall remain that of the flexible array member, even if this would differ from that of the replacement array. If this array would have no elements, it behaves as if it had one element but the behavior is undefined if any attempt is made to access that element
or to generate a pointer one past it.



Неудобства наступают позже, из-за того, что структура всегда выравнивается на 4096, а не имеет размер 4096 и выравнивается на 4, 8, 16 байт.

bormant ★★★★★
()
Ответ на: комментарий от bormant

константно вычислим сразу после завершения объявления типа

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

jsforever
() автор топика
Ответ на: комментарий от COKPOWEHEU

вы знаете способ лучше?

Для начала надо понять что именно требуется и главное - зачем. А уже от этого плясать.

Вариант с наследованием конечно самый прямой, но опять таки - для чего именно? Что ужасного случится если sizeof!=4К?

AntonI ★★★★★
()
Ответ на: комментарий от jsforever

тоже мне Даг Голова нашелся…

— Может, ты знаешь что-то такое, чего я не знаю?
— Слушай, я наверное очень много знаю такого, о чем ты даже не подозреваешь.
AntonI ★★★★★
()
Ответ на: комментарий от AntonI

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

jsforever
() автор топика
Ответ на: комментарий от jsforever

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

А уж дойти до того что большинство решений сломается из за выравнивания Вы точно не способны.

обделаться в споре

Настало время афигительных историй!

AntonI ★★★★★
()
Ответ на: комментарий от COKPOWEHEU

error

struct X{ alignas(4096)


Строго говоря, оно перед int i;.
Если компилятор ниже C23, то _Alignas вместо alignas.
Если ниже C11, то стандартизованного способа нет.

bormant ★★★★★
()
Ответ на: комментарий от AntonI

Настало время афигительных историй!

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

и да, очередные афигительные истории рядом. что имеем - гуманитарий сел в лужу на всех вопросах, по которым он пытался со мной спорить. далее, когда он осознал своё положение, что он делает? правильно, декларирует «я буду глумится над тобой» - т. е. он будет пытаться мне гадить и мстить за свою некомпетентность.

ещё раз, он будет за свою некомпетентность мстить мне. хотя казалось бы, вот он никак и никем не состоялся в жизни, но причём здесь я? а притом, что нужно всех убедить что гуманитарий что-то из себя представляет, а у всех несогласных забрать возможность отвечать.

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

jsforever
() автор топика
Ответ на: комментарий от bormant

ну вот, знай своё место и больше не мечтай так сильно.

jsforever
() автор топика
Ответ на: комментарий от AntonI

Не заметил, как любой технический тред с твоим участием скатывается в срач? И как он каждый раз начинается со слова ‘python’ и заканчивается словом ‘глумиться’? Не отвечай, я все равно читать не буду, вопрос риторический. Я просто слышал ты еще и людей учишь, так вот мне их искренне жаль.

PhD
()
Ответ на: комментарий от PhD

Бггг, то есть с одной стороны Вы тщательно следите за всеми техническими тредами где я что то пишу, а с другой стороны принципиально не читаете то что я пишу? Вы каких наук PhD, часом не теологических?

Что то с логикой у Вас беда-беда прям какая то…

AntonI ★★★★★
()

Вот тебе ещё вариант:

template <std::size_t SIZE, std::size_t BUF_SIZE>
struct X {
    int i;
    float f;
    uint8_t p;
    char buf[BUF_SIZE];
};

template <template <std::size_t, std::size_t> class T, std::size_t SIZE = 4096>
struct Type : public T<SIZE, SIZE - sizeof(T<SIZE, 0>)> {};

Type<X> t {{.i = 1, .f = 0.2, .p = 50, .buf = "test"}};
Ivan_qrt ★★★★★
()
Ответ на: комментарий от Ivan_qrt

А ещё лучше так:

template <std::size_t BUF_SIZE>
struct X {
    int i;
    float f;
    uint8_t p;
    char buf[BUF_SIZE];
};

template <template <std::size_t> class T, std::size_t SIZE = 4096>
using Type = T<SIZE - sizeof(T<0>)>;

Type<X> t {.i = 1, .f = 0.2, .p = 50, .buf = "test"};

Что характерно в этих вариантах массив не обязан быть последним в структуре.

Ivan_qrt ★★★★★
()
Последнее исправление: Ivan_qrt (всего исправлений: 1)
Ответ на: комментарий от AntonI

не теологических?

Что то с логикой

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

LamerOk ★★★★★
()
Ответ на: комментарий от AntonI

как std::vector< T > &p

да, так и делаю собственно, спасибо

AndreyKl ★★★★★
()
Ответ на: комментарий от bormant

Как только вылезут за пределы object, так сразу и.

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

AndreyKl ★★★★★
()
Ответ на: комментарий от bormant

Перечитал тред, обдумал эту мысль. Вероятно вы правы, jsforever скорее всего действительно знал что массивы имеют длину и хранят её где то. Спасибо за поправку.

jsforever если это так, выходит в этом случае я хорошо знаю тему для одиннадцатиклассника. За сим в данный спор больше не лезу.

AndreyKl ★★★★★
()
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.