2013-07-15 2 views
0

Предположим, что я пишу функцию, которая принимает float a[] и смещение в этот массив и возвращает элемент с таким смещением. Можно ли использовать подписьУместно ли использовать off_t для смещений без байта?

float foo(float* a, off_t offset); 

для этого? Или off_t относится только к смещениям в байтах, а не к арифметике указателя с произвольными размерами элементов? то есть разумно ли говорить a[offset], когда смещение имеет тип off_t?

Библиотека GNU C Справочное руководство говорит:

off_t 
    This is a signed integer type used to represent file sizes. 

, но это не говорит мне много.

Моя интуиция заключается в том, что ответ «нет», поскольку фактический адрес, используемый в [смещении], является адресом смещения + sizeof (float) *, поэтому «sizeof (float) * offset» - это off_t , а sizeof (float) - size_t, и оба являются константами с «размерами».

Примечание: Смещение может быть отрицательным.

+0

Довольно уверен, что доступ к отрицательным смещениям указателя считается злым. – zneak

+0

@zneak: Может быть, и я не намерен, но 'a [-1]' вполне допустимый код. – einpoklum

+0

@zneak Совсем нет. Почему это должно быть. –

ответ

0

Возможно, ответ заключается в использовании ptrdiff_t? Это...

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

Что вы думаете?

+0

Хотя другие предложили «ptrdiff_t» после меня, все они сделали заявления, на которых я действительно не согласен. Извините ребята. – einpoklum

2

Вы можете использовать size_t или ptrdiff_t как тип индекса (ваш второй параметр больше является индексом внутри массива с плавающей точкой, чем смещение).

Ваше использование - это индекс, а не смещение. Обратите внимание, что стандартный макрос offsetof определен для возврата смещений байтов!

На практике вы могли бы использовать только int или unsigned, если только вы не верите, что ваш массив может иметь миллиарды компонентов.

Возможно, вы захотите, чтобы #include <stdint.h> (или <cstdint> с недавним C++) и имели явные типы типов, такие как int32_t для ваших индексов.

По причинам источник удобочитаемости, вы можете определить

typedef unsigned index_t; 

, а затем использовать его, например,

float foo(float a[], index_t i); 

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

+0

Общеизвестно ли определение типа 'index_t'? Кроме того, что, если я хочу смещение, которое потенциально может быть отрицательным? – einpoklum

+0

Это не распространено, но люди обычно просто используют 'int' ... –

+0

Он не может использовать' size_t', потому что смещения могут быть отрицательными. В памяти правильным типом будет 'ptrdiff_t', или если домен или проверка входных значений гарантируют, что переполнение не может существовать,' int'. –

1

Я бы сказал, что это не подходит, так как

  1. off_t является (предназначено быть) используется для представления размера файла
  2. off_t является знаковым типом.

Я хотел бы пойти на size_type (обычно «ЬурейеЕ» название изд для size_t), который является один используется StD контейнеров.

+1

'std :: vector :: size_type' является typedef' size_t' (который существует в C). 'size_type' не существует как отдельный тип. – zneak

+0

Но как может off_t указать размер файла? Смещение не является размером ... и смещение может быть отрицательным, а размер не может. – einpoklum

+0

@einpoklum, он используется с файловыми манипуляциями, например 'fseek' /' lseek'. 'size_t', с другой стороны, определяется как способный удерживать максимальный размер любого массива на платформе. Звучит скорее как то, что вы ищете. – zneak

2

Есть ли веская причина, почему вы просто не используете int? Это тип по умолчанию для интегральных значений в C++ и должен использоваться , если нет веской причины не делать этого.

Конечно, одна хорошая причина может заключаться в том, что она может переполняться. Если контекст таков, что вы можете получить очень большие массивы , вы можете использовать ptrdiff_t, который определяется (в C и C++) как тип, полученный в результате вычитания двух указателей : другими словами, он гарантированно не переполняется (когда используется как смещение) для всех типов с размером больше 1.

+0

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

+0

@einpoklum «Официальный» источник является стандартом: в §3.1.1/2, простой 'int' является естественным типом, а остальные -« отвечают специальным потребностям ». На практике использование любого другого типа , чем 'int', говорит о необходимости особой необходимости. Возможно, дополнительный диапазон или экономия места. Или вам нужна modulo арифметика неподписанных типов или выполняете манипуляции с битами. (Использование неподписанного типа обычно является четким указанием на то, что вы не связаны с арифметическими данными.) –

Смежные вопросы