Арифметика адреса с массивом указателя на строку [duplicate]

Я заметил, что Internet Explorer 11 становится невероятно медленным, когда вырезаете данные, подобные jeremy. Это верно для Chrome, но у IE возникает проблема при передаче разрезанных данных в Blob-Constructor. На моей машине, передавая 5 МБ данных, происходит сбой в IE, а потребление памяти идет через крышу. Chrome быстро создает blob.

Запустите этот код для сравнения:

var byteArrays = [],
    megaBytes = 2,
    byteArray = new Uint8Array(megaBytes*1024*1024),
    block,
    blobSlowOnIE, blobFastOnIE,
    i;

for (i = 0; i < (megaBytes*1024); i++) {
    block = new Uint8Array(1024);
    byteArrays.push(block);
}

//debugger;

console.profile("No Slices");
blobSlowOnIE = new Blob(byteArrays,  { type: 'text/plain' });
console.profileEnd();

console.profile("Slices");
blobFastOnIE = new Blob([byteArray],  { type: 'text/plain' });
console.profileEnd();

Поэтому я решил включить оба метода, описанные jeremy в одну функцию. Кредиты идут к нему за это.

function base64toBlob(base64Data, contentType, sliceSize) {

    var byteCharacters,
        byteArray,
        byteNumbers,
        blobData,
        blob;

    contentType = contentType || '';

    byteCharacters = atob(base64Data);

    // Get blob data sliced or not
    blobData = sliceSize ? getBlobDataSliced() : getBlobDataAtOnce();

    blob = new Blob(blobData, { type: contentType });

    return blob;


    /*
     * Get blob data in one slice.
     * => Fast in IE on new Blob(...)
     */
    function getBlobDataAtOnce() {
        byteNumbers = new Array(byteCharacters.length);

        for (var i = 0; i < byteCharacters.length; i++) {
            byteNumbers[i] = byteCharacters.charCodeAt(i);
        }

        byteArray = new Uint8Array(byteNumbers);

        return [byteArray];
    }

    /*
     * Get blob data in multiple slices.
     * => Slow in IE on new Blob(...)
     */
    function getBlobDataSliced() {

        var slice,
            byteArrays = [];

        for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
            slice = byteCharacters.slice(offset, offset + sliceSize);

            byteNumbers = new Array(slice.length);

            for (var i = 0; i < slice.length; i++) {
                byteNumbers[i] = slice.charCodeAt(i);
            }

            byteArray = new Uint8Array(byteNumbers);

            // Add slice
            byteArrays.push(byteArray);
        }

        return byteArrays;
    }
}
6
задан Kevin Reid 9 June 2013 в 14:56
поделиться

1 ответ

1) Указатели не являются массивами. Массивы не являются указателями. Не думайте о них так, потому что они разные. Как я могу это доказать? Подумайте, как они выглядят в памяти:

Наш массив arr имеет длину 10 символов. Он содержит «Привет», но подождите, это еще не все! Поскольку у нас есть статически объявленный массив дольше, чем наше сообщение, мы получаем кучу NULL символов ('\0'), брошенных бесплатно! Также обратите внимание на то, что имя arr концептуально привязано к смежным символам (оно не указывает ни на что). enter image description here [/g0]

Далее рассмотрим, как наш указатель будет выглядеть в памяти: enter image description here [/g1] Обратите внимание, что мы указываем на массив символов в некотором месте в памяти только для чтения.

Таким образом, хотя оба arr и ptr были инициализированы одинаково, содержимое / местоположение каждого на самом деле различно.

Это ключевой момент: ptr - это переменная, мы можем указать ее на что угодно, arr - константа, она всегда будет ссылаться на этот блок из 10 символов.


2) [] является оператором «add and deference», который может использоваться по адресу. Это означает, что arr[0] совпадает с *(arr+0). Итак, да, сделайте это:

printf("%c %c", *(arr+1), *(ptr+1));

Дает вам вывод «e e». Это не потому, что массивы являются указателями, потому что имя массива arr и указатель ptr оба передают вам адрес.

Ключевой пункт для # 2: Оператор deference * и оператор add и deference [] не относятся к указателям и массивам соответственно. Эти операторы просто работают с адресами.


3) У меня нет очень простого ответа ... поэтому давайте забудем наши массивы символов на секунду и рассмотрим этот пример для Объяснение:

int b;   //this is integer type
&b;      //this is the address of the int b, right?

int c[]; //this is the array of ints
&c;      //this would be the address of the array, right?

Итак, это довольно понятно, как об этом:

*c;   //that's the first element in the array

Что говорит вам эта строка кода? Если я уважаю c, тогда получаю int. Это означает, что просто c - это адрес. Поскольку это начало массива, это адрес массива, а также адрес первого элемента в массиве, таким образом, с точки зрения значения:

c == &c;

4) Позвольте мне уйти тема для второго здесь ... этот последний вопрос является частью путаницы адресной арифметики. В какой-то момент я увидел вопрос о SO, подразумевающий, что адреса - это целые значения ... Вам нужно понять, что в адресах C есть знание типа. То есть:

iarr+1; //We added 1 to the address, so we moved 4 bytes
arr+1;  //we added 1 to the address, so we moved 1 byte

В основном sizeof(int) равно 4, а sizeof(char) равно 1. Таким образом, «добавление 1 к массиву» не так просто, как кажется.

Итак, вернемся к вопросу, почему arr+1 отличается от &arr+1? Первый добавляет 1 * sizeof(char) = 1 к адресу, второй добавляет 1 * sizeof(arr) = 10 к адресу.

Вот почему, хотя они оба «добавляют только 1», они дают разные результаты.

17
ответ дан Mike 18 August 2018 в 05:36
поделиться
  • 1
    Как ваш ответ на Q4 относится к Q4? – David Heffernan 1 October 2012 в 16:38
  • 2
    «Вот почему ptr считается значением l». Нет, это не значит, что ptr считается lvalue ; ведь arr также считается lvalue . – CB Bailey 1 October 2012 в 16:46
  • 3
    @DavidHeffernan - я немного переписал Q & amp; A4. Помогает ли это показать, как они связаны? Просто хотел пояснить, что +1 по адресу не всегда одинаковый (в зависимости от того, какой тип адрес) – Mike 1 October 2012 в 16:50
  • 4
    Это Q, который нужно изменить. Повторите чтение Q4. – David Heffernan 1 October 2012 в 16:51
  • 5
    @Mike: Я не понимаю, почему вы вечером упоминаете lvalue . arr и ptr являются lvalues ​​, но так же каждое выражение является идентификатором, обозначающим переменную или ссылку. Это просто не похоже на обсуждение указателя и массива. – CB Bailey 1 October 2012 в 17:04
Другие вопросы по тегам:

Похожие вопросы: