LINUX.ORG.RU

насколько вообще нужны платформо-зависимые типы?

 


0

3

Обычные грабли при написании портируемых программ на си это, скажем, различные размеры int, (без)знаковость char итп.

И вот что подумалось. Эти все навороты вообще нужны? Мне кажется, это тяжкое наследие старины когда байт мог быть и не 8бит. Сейчас от этого лишь проблемы. Т.е. имеет смысл перейти, скажем, int8_t, int32_t... А вы что думаете? И нужны ли дополнительные обёртки типа size_t?

★★★★★

особенно весело бывает когда не знаешь чему равен (int) 'a'.

dzidzitop ★★
()

C - это по сути обертка над ассемблером, поэтому авторы решили сделать платформозависимые типы. Совершенно согласен, что лучше бы размер типов был стандартизован, как в Java - меньше было бы ошибок.

m0rph ★★★★★
()

Чем тебя uint_fastN_t, int_fastN_t, uint_leastN_t, int_leastN_t, uintmax_t и intmax_t не устраивают? Что ты к этим intN_t и uintN_t привязался, особенно если учесть, что они опциональны?

anonymous
()

Вообще не понимаю, как можно использовать такие типы, т.к. никогда не знаешь, прокатит for(int i = 0; i < 500; ++i) или инт восьмибитный.

unC0Rr ★★★★★
()

[C] Бесполезные типы данных?

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

char можно использовать, например, как 7-битный символ ascii.

short и long [double] вообще никогда не надо использовать, stdint наше всё.

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

Типы с указанной шириной имеют смысл только для ввода/вывода.

А если мы знаем, что работа с меньшей разрядностью быстрее, почему явно это не задать?

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

Что-что? В стандарте есть signed и unsigned типы. Если вы явно этого не указываете, то компилятор выберет его на свое усмотрение.

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

По тому, что такой код будет более платформозависим, и такие оптимизации должен делать компилятор.

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

А если мы знаем, что работа с меньшей разрядностью быстрее, почему явно это не задать?

Потому что процессоры разные бывают, кроме x86 есть другие архитектуры, на которых твой говнокод наоборот тормозить будет.

$ cat test.c
#include <stdint.h>

uint16_t sum_v1(uint8_t *data)
{
    uint8_t i;
    uint16_t sum = 0;

    for (i = 0; i < 32; i++)
        sum += *(data++);

    return sum;
}

int sum_v2(char *data)
{
    int i;
    int sum = 0;

    for (i = 0; i < 32; i++)
        sum += *(data++);

    return sum;
}
$ arm-none-linux-gnueabi-gcc -c -O3 test.c &&  arm-none-linux-gnueabi-objdump -d test.o

test.o:     file format elf32-littlearm


Disassembly of section .text:

00000000 <sum_v1>:
   0:	e3a01000 	mov	r1, #0	; 0x0
   4:	e1a02001 	mov	r2, r1
   8:	e7d03002 	ldrb	r3, [r0, r2]
   c:	e2822001 	add	r2, r2, #1	; 0x1
  10:	e0813003 	add	r3, r1, r3
  14:	e1a03803 	lsl	r3, r3, #16    <<< запомни говнокодер
  18:	e3520020 	cmp	r2, #32	; 0x20
  1c:	e1a01823 	lsr	r1, r3, #16    <<< не у всех  блеать есть регистры разной ширины
  20:	1afffff8 	bne	8 <sum_v1+0x8>
  24:	e1a00001 	mov	r0, r1
  28:	e12fff1e 	bx	lr

0000002c <sum_v2>:
  2c:	e3a01000 	mov	r1, #0	; 0x0
  30:	e1a02001 	mov	r2, r1
  34:	e7d03002 	ldrb	r3, [r0, r2]
  38:	e2822001 	add	r2, r2, #1	; 0x1
  3c:	e3520020 	cmp	r2, #32	; 0x20
  40:	e0811003 	add	r1, r1, r3
  44:	1afffffa 	bne	34 <sum_v2+0x8>
  48:	e1a00001 	mov	r0, r1
  4c:	e12fff1e 	bx	lr

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

А если мы знаем, что работа с меньшей разрядностью быстрее, почему явно это не задать?

Если знаете - задавайте.

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

А зачем тебе это явно задавать? Используй uint_fastN_t или int_fastN_t, где N минимальное из 8, 16, 32, 64 количество бит достаточное для хранения числа.

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

Некоторых ошибок можно было бы избежать. Вот какой смысл делать char знаковым на одних платформах и беззнаковым на других?

Да, был удивлён, когда простенький код, работающий на i386, x86_64, сбойнул на ARMе. Оказалось, что char - это не синоним signed char, а такой себе typedef на выбор.

Если почитать советы по оптимизации для АРМа, то причина подобного (а также, как лучше организовывать циклы) в том, как они придумали свою архитектуру.

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

компилятор выберет его на свое усмотрение.

O_o ты не прав. Это задаётся в «настрйках» архитектуры.

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

Как твоё мнение, я могу сейчас идти на собеседование по си? :)

Да, конечно. Вопрос в том, какие там требования :)

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

А конкретно куда смотреть? Не нашел там ничего о знаковости char.

Да и в любом случае ссылка должна быть куда-то в интеловские мануалы. Никогда не слышал, чтобы интел задавал, какой у него байт.

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

Да, конечно

Благословление получено, теперь не страшно :).

какие там требования

Написание «системного» софта на питоне. Си нужен для писания обвязок и понимания того что делают настоящие системные программисты.

true_admin ★★★★★
() автор топика

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

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

Ну вообще могу привести вот такой пруф, хотя там сделана оговорка, что char - исключение из этого правила.

Что-то не могу найти официальный текст стандарта, где-то брал его в pdf`ке, но не помню где.

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

Вообще-то, в современных RISC-архитектурах все регистры общего назначения имеют одинаковый размер

Ahem

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

А какие именно из перечисленных регистров (я так понимаю, что это DSP-блок, прикрученный к какому-то универсальному ЦП) являются регистрами общего назначения?

tailgunner ★★★★★
()

для использования возможностей конкретной платформы по максимому все го лиш.

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

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

автор, судя по всему, даже не представляет, что в мире есть не только интел-совместимые процессоры.

Автор представляет. Endianess это другая, отдельная проблема.

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

Вот такой пруф

Там же написано:

The values of the columns Size and Range depend on the system the program is compiled for. The values shown above are those found on most 32-bit systems. But for other systems, the general specification is that int has the natural size suggested by the system architecture (one «word») and the four integer types char, short, int and long must each one be at least as large as the one preceding it, with char being always one byte in size.

Т.е. написано что это всё зависит от системы. Cast unsigned.

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

Аккумуляторы же.
Кстати, там ещё есть

3.3.1.1 Регистровый файл
Исходные операнды и результаты операций ALU хранятся в регистровом файле (RF), который представляет собой набор из 32-х программно-доступных 16-разрядных регистров R0–R31, которые могут конфигурироваться в 16 32-разрядных регистров.

Регистровый файл (RF) представляет собой многопортовую оперативную память с организацией 32 слова (NB) по 16 бит или 16 слов по 32 бита. При помощи RF осуществляется параллельное чтение и запись нескольких операндов в соответствии с исполняемой операцией.

Я бы не сказал, что он универсальный, его позиционируют либо как встраиваемую числодробилку (ха-ха, да) либо как обработчик видеопотока, ЕМНИП. Хотя на него можно поставить Linux, если верить докам.

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

Кто-то еще пишет обвязки на Си?

Я хз, если честно, что будет. Кмк, всего на ctypes и cython не напишешь. По крайней мере, элегантного решения как работать из питона с ioctl мы (лоровцы) не нашли. Тогда всё упёрлось в раскрытие макросов. Вроде, даже каких-то монстров с gcc-xml городили.

Поэтому для работы, например, с perf_event_open() я писал мини-либу на си которую уже через ctypes подключал к питону. Так же и с fuse — у него в протоколе структуры переменной длины (с опциональными полями, если не путаю). Я так и не понял как с этим нормально работать из питона. Имхо, проще отдельную либу-прослойку сделать чем секс с модулем struct.

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

А какие именно из перечисленных регистров (я так понимаю, что это DSP-блок, прикрученный к какому-то универсальному ЦП) являются регистрами общего назначения?

Аккумуляторы же.

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

могут конфигурироваться

Каким образом?

Да и вообще, относить DSP с их выморочной архитектурой к «современным RISC»....

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

элегантного решения как работать из питона с ioctl мы (лоровцы) не нашли

Вызываешь os.ioctl, не?

Так же и с fuse — у него в протоколе структуры переменной длины (с опциональными полями, если не путаю)

Никаких проблем.

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

Вызываешь os.ioctl, не?

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

Никаких проблем.

А как? Допустим, есть такая структура:

struct Answer {
size_t len;
char answer[];
}

В Answer.answer ответ, его длина в len. Как с таким в питоне работать?

PS возможно, неточно описываю проблему, уже не помню с чем пришлось столкнуться.

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

Как с таким в питоне работать?

Для такой ерунды хватит и struct.unpack; я написал себе библиотечку двоичного парсинга на ctypes, которая автоматически создает ctypes-дескрипторы для типов с VLA.

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

Да это понятно, что размеры типов зависят от платформы (железо + ОС + компилятор). Я же придрался только к выбору, каким будет char. Наверное, бывают архитектуры, где арифметика только знаковая или наоборот, тогда можно говорить, что знаковость char определяется железом. Но как правило (для интела - точно) это не так, и выбор делают компиляторщики из других соображений.

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

выбор делают компиляторщики

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

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

32 бита. Всегда.

byte - 8 bit
short - 16 bit
int - 32 bit
long - 64 bit
float - 32 bit
double - 64 bit
char - 16 bit
boolean - 8 bit
LongLiveUbuntu ★★★★★
()
Последнее исправление: LongLiveUbuntu (всего исправлений: 1)
Ответ на: комментарий от tailgunner

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

Ну да.

Каким образом?

Каб я помнил. Могу мануал скинуть.

Да и вообще, относить DSP с их выморочной архитектурой к «современным RISC»

RISC — это пардигма архитектуры чего? Процессора. DSP-ядро — часть процессора. Проблемы?
// Фигачить весь код под DSP никто не заставляет же; там пишется только работа с портами и памятью.

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

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

Ну да.

Тогда непонятно, почему ты упомянул их в разговоре о РОН.

RISC — это пардигма архитектуры чего? Процессора. DSP-ядро — часть процессора. Проблемы?

Никаких. Вполне очевидно, что слова annulen о современных RISC-процессорах не относятся к химерам вроде RISC+DSP.

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

Тогда непонятно, почему ты упомянул их в разговоре о РОН.

Не обратил внимания. После я привёл регистры из RF.

Никаких. Вполне очевидно, что слова annulen о современных RISC-процессорах не относятся к химерам вроде RISC+DSP.

Архитектура этого процессора — MIPS32. Или MIPS уже не RISC?

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

Архитектура этого процессора — MIPS32. Или MIPS уже не RISC?

Ты путаешь архитектуру ядра и расширений. У х86 тоже есть FPU и SIMD расширения со своими регистрами которые НЕ являются РОН - АЛУ ядра не имеет к ним доступа.

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

я написал себе библиотечку двоичного парсинга на ctypes

Можно на неё одним глазом посмотреть?

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

Так держать.

Ты не понял того, что тебе сказали трижды, так что не удивляйся.

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

Можно на неё одним глазом посмотреть?

Думаю, начальство будет недовольно. Но суть сводится к двум строчкам:

vla_ctyp = type(nm, (Structure,), {})
vla_ctyp._fields_ = [(vla_name, vla_elt_ctyp*vla_len)]
tailgunner ★★★★★
()
Ответ на: комментарий от Deleted

Архитектура этого процессора — MIPS32

Что-то не припомню в мипсе таких регистров.

annulen ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.