В программировании шаг массива (также называемый приращением , шагом или размером шага ) — это количество ячеек в памяти между началами последовательных элементов массива , измеряемое в байтах или в единицах размера элементов массива. Шаг не может быть меньше размера элемента, но может быть больше, указывая на дополнительное пространство между элементами.
Массив с шагом точно такого же размера, как и размер каждого из его элементов, является непрерывным в памяти. Иногда говорят, что такие массивы имеют единичный шаг . Массивы с единичным шагом иногда более эффективны, чем массивы с неединичным шагом, но массивы с неединичным шагом могут быть более эффективными для двумерных или многомерных массивов , в зависимости от эффектов кэширования и используемых шаблонов доступа [ необходима цитата ] . Это можно отнести к принципу локальности , в частности пространственной локальности .
Массивы могут иметь шаг, превышающий ширину их элементов в байтах, по крайней мере в двух случаях:
Некоторые языки позволяют обрабатывать массивы структур как перекрывающиеся параллельные массивы с неединичным шагом:
#include <stdio.h> struct MyRecord { int value ; char * text ; }; /** Вывести содержимое массива целых чисел с заданным шагом. Обратите внимание, что size_t — правильный тип, так как int может переполняться. */ void print_some_ints ( const int * arr , int length , size_t stride ) { int i ; printf ( "Адрес \t\t Значение \n " ); for ( i = 0 ; i < length ; ++ i ) { printf ( "%p \t %d \n " , arr , arr [ 0 ]); arr = ( int * )(( unsigned char * ) arr + stride ); } } int main ( void ) { int ints [ 100 ] = { 0 }; struct MyRecord records [ 100 ] = { 0 }; print_some_ints ( & ints [ 0 ], 100 , sizeof ints [ 0 ]); print_some_ints ( & records [ 0 ] .value , 100 , sizeof records [ 0 ]); return 0 ; }
Эта идиома является формой каламбурной игры .
Некоторые языки, такие как PL/I или Fortran, допускают так называемое поперечное сечение массива , которое выбирает определенные столбцы или строки из большего массива. [1] : стр.262 Например, если двумерный массив объявлен как
объявить some_array ( 12 , 2 ) фиксированным ;
массив одного измерения, состоящий только из второго столбца, может быть обозначен как
некоторый_массив ( * , 2 )
Неединичный шаг особенно полезен для изображений. Он позволяет создавать подизображения без копирования данных пикселей. Пример Java:
public class GrayscaleImage { private final int width , height , widthStride ; /** Данные пикселей. В этом примере пиксели в одной строке всегда считаются смежными. */ private final byte [] pixels ; /** Смещение первого пикселя в пикселях */ private final int offset ; /** Конструктор для смежных данных */ public Image ( int width , int height , byte [] pixels ) { this . width = width ; this . height = height ; this . pixels = pixels ; this . offset = 0 ; this . widthStride = width ; } /** Конструктор подраздела */ public Image ( int width , int height , byte [] pixels , int offset , int widthStride ) { this . width = width ; this . height = height ; this . pixels = pixels ; this . offset = offset ; this . widthStride = widthStride ; } /** Возвращает подобласть этого изображения как новое изображение. Это и новое изображение разделяют пиксели, поэтому изменения в возвращенном изображении будут отражены в этом изображении. */ public Image crop ( int x1 , int y1 , int x2 , int y2 ) { return new Image ( x2 - x1 , y2 - y1 , pixels , offset + y1 * widthStride + x1 , widthStride ); } /** Возвращает значение пикселя в указанной координате */ public byte getPixelAt ( int x , int y ) { return pixels [ offset + y * widthStride + x ] ; } }