В C, почему приращение указателя добавляет размер типа, на который ссылается указатель вместо 1? [Дубликат]

Только одна строка! path и line являются строками

import java.nio.file.Files;
import java.nio.file.Paths;

Files.write(Paths.get(path), lines.getBytes());
13
задан mko 22 July 2012 в 08:04
поделиться

6 ответов

Подумайте, что такое указатель ... это адрес памяти. Каждый байт в памяти имеет адрес. Итак, если у вас есть int, то есть 4 байта, а его адрес равен 1000, 1001 фактически является вторым байтом этого int, а 1002 - третьим байтом, а 1003 - четвертым. Поскольку размер int может отличаться от компилятора к компилятору, крайне важно, чтобы при инкрементах указателя вы не получили адрес некоторой средней точки в int. Таким образом, задача определения количества пропущенных байтов, основанных на вашем типе данных, обрабатывается для вас, и вы можете просто использовать любое значение, которое вы получаете, и не беспокоиться об этом.

Как указывает Базиле Старинквич , эта сумма будет варьироваться в зависимости от свойства sizeof указанного элемента данных. Очень легко забыть, что хотя адреса последовательны, указатели на ваши объекты должны учитывать фактическое пространство памяти, необходимое для размещения этих объектов.

21
ответ дан Yuri Tretyakov 21 August 2018 в 07:09
поделиться

Вам действительно нужно потратить время, чтобы прочитать хорошую книгу языка программирования C (например, K & amp; R "язык программирования C" )

Арифметика указателя - сложный вопрос. Добавление указателя означает переход к следующему остроконечному элементу. Таким образом, адрес увеличивается на sizeof заостренный элемент.

7
ответ дан Basile Starynkevitch 21 August 2018 в 07:09
поделиться
  • 1
    Я собираюсь просить эту книгу из библиотеки сегодня! – mko 22 July 2012 в 09:08

Указатель используется для указания на определенный байт маркировки памяти, где объект был выделен (технически он может указывать в любом месте, но именно так он используется). Когда вы выполняете арифметику указателей, она работает в зависимости от размера объектов, на которые указывает. В вашем случае это указатель на целые числа, размер которых равен 4 байтам.

2
ответ дан Jimmy 21 August 2018 в 07:09
поделиться

Рассмотрим указатель p. Выражение p+n похоже на (unsigned char *)p + n * sizeof *p (потому что sizeof(unsigned char) == 1). Попробуйте следующее:

#include <stdio.h>
#define N   3

int
main(void)
{
    int i;
    int *p = &i;
    printf("%p\n", (void *)p);
    printf("%p\n", (void *)(p + N));
    printf("%p\n", (void *)((unsigned char *)p + N * sizeof *p));
    return 0;
}
1
ответ дан md5 21 August 2018 в 07:09
поделиться

Короткий ответ

Адрес указателя будет увеличен на sizeof(T), где T - тип, на который указывает. Таким образом, для int указатель будет увеличен на sizeof(int).

Почему?

Ну, в первую очередь, стандарт требует этого. Причина, по которой это поведение полезна (кроме совместимости с C), заключается в том, что, когда у вас есть структура данных, которая использует непрерывную память, например массив или std::vector, вы можете перейти к следующему элементу массива, просто добавив один к указателю. Если вы хотите перейти к n-му элементу в контейнере, вы просто добавите n.

Возможность писать firstAddress + 2 намного проще, чем firstAddress + (sizeof(T) * 2), и помогает предотвратить ошибки, возникающие у разработчиков, предполагающих sizeof(int) 4 (это может быть не так) и писать код, как firstAddress + (4 * 2).

На самом деле, когда вы говорите myArray[4], вы говорите myArray + 4. Это причина, по которой индексы массивов начинаются с 0; вы просто добавляете 0, чтобы получить первый элемент (т. е. myArray указывает на первый элемент массива) и n, чтобы получить n-й.

Что делать, если я хочу переместить один байт за раз?

sizeof(char) гарантированно будет иметь один байт, поэтому вы можете использовать char*, если хотите переместить один байт за раз.

5
ответ дан OMGtechy 21 August 2018 в 07:09
поделиться

Поскольку указатели предназначены для совместимости с массивами:

*(pointer + offset)

эквивалентно

pointer[offset]

Таким образом, арифметика указателя не работает в терминах байтов, но в терминов блоков sizeof(pointer base type) -bytes.

28
ответ дан user 21 August 2018 в 07:09
поделиться
  • 1
    для 64-битных машин она может достигать 8 байтов. – Aftnix 22 July 2012 в 08:10
  • 2
    @Aftnix да, но в чем проблема? – user 22 July 2012 в 08:11
  • 3
    @Aftnix и нет, подумайте о создании указателя на структуру размером в 256 байт ... – user 22 July 2012 в 08:11
  • 4
    указатель будет достаточно большим, чтобы сохранить адрес памяти платформы. Если вам нужно 8 байтов для хранения адреса памяти, оно будет равно 8 байтам, независимо от того, на что указывает. Я просто говорю, что вы должны указать на это в своем ответе ради общности. нет ничего плохого в вашем ответе, но арифметика указателя имеет смысл, если у вас есть «фиксированный». переменная указателя размера. Я просто говорю, прежде чем указывать принцип арифметики указателя, вы должны сказать, что каждая платформа имеет собственный фиксированный размер указателя. Вот почему арифметика указателей является последовательной на разных платформах. – Aftnix 22 July 2012 в 08:20
  • 5
    +1 для того, чтобы сообщить мне о связи между массивом и указателем. но я не могу заставить ваш код работать: printf (& quot;% p & quot;, ptr [1]) – mko 22 July 2012 в 09:22
Другие вопросы по тегам:

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