C: массив указателей (индексирование и инкремент)

Модератор: Модераторы разделов

vipermagi
Сообщения: 83
ОС: AgiliaLinux

C: массив указателей

Сообщение vipermagi »

В книжке Кернигана и Ритчи есть такой пример

Код: Выделить всё

#include <stdio.h>
/* echo: вывод аргументов командной строки; 2-я версия */
main(int argc, char *argv[])
{
  while (--argc > 0)
    printf("%s%s", *++argv, (argc > 1) ? " " : "");
  printf("\n");
  return 0;
}


И ниже написано:
Поскольку argv — это указатель на начало массива строковых аргументов,увеличение его на единицу (++argv) приводит к тому, что он начинает указывать на элемент126 Глава 5argv[l].


В чём прикол? По моему разумению если добавить в любой адрес единичку то он переключится на следующий байт. Но ведь для хранения адреса нужно 8 байт(в моём случае). То есть в массиве, размеренном по 8 байт, данный инкремент должен будет переместить значение адреса на следующий байт того же элемента, а не на байт начала следующего? Чего-то я не догоняю. Или я невнимательно читаю или там непонятно написано.
Спасибо сказали:

Аватара пользователя
Rootlexx
Бывший модератор
Сообщения: 4417
Статус: GNU generation
ОС: Debian GNU/Linux

Re: C: массив указателей

Сообщение Rootlexx »

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

vipermagi
Сообщения: 83
ОС: AgiliaLinux

Re: C: массив указателей

Сообщение vipermagi »

Чё-то у меня внимательность понизилась, нашёл строку в книжке, где это прямым текстом написано.

Значит, чтобы получить доступ к адресу следующего байта, надо сделать приведение к void* ?
Спасибо сказали:

Аватара пользователя
Rootlexx
Бывший модератор
Сообщения: 4417
Статус: GNU generation
ОС: Debian GNU/Linux

Re: C: массив указателей

Сообщение Rootlexx »

vipermagi писал(а):
22.08.2013 17:08
Значит, чтобы получить доступ к адресу следующего байта, надо сделать приведение к void* ?

Да. Или к char *.
Спасибо сказали:

Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: C: массив указателей

Сообщение drBatty »

vipermagi писал(а):
22.08.2013 17:08
Значит, чтобы получить доступ к адресу следующего байта, надо сделать приведение к void* ?

НЕТ! Это быдлокод. Размер того, на что указывает void*, НЕ ОПРЕДЕЛЁН!

А вот размер _указателя_ void* вполне определён, правда только во время компиляции (на другой архитектуре он будет другим). На i686 размер sizeof(char*) == sizeof(void*) == 4 (на x86 уже 8).

Если вы складываете указатель с int, то этот int неявно преобразуется в ptrdiff_t, это специальный тип, который имеет разность двух указателей одного типа и одного и того-же массива (это ВАЖНО! результат вычитания разных массивов НЕ ИМЕЕТ СМЫСЛА).

Тип argv -- массив указателей на char. Т.е. это массив, который состоит из чисел размером 4 байта (на i686). Прибавляя единицу, вы переходите на след. эл-т этого массива, внутри кода адрес увеличивается на 4 (для i686).
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:

BratSinot
Сообщения: 812
ОС: Slackware64

Re: C: массив указателей

Сообщение BratSinot »

Rootlexx писал(а):
22.08.2013 17:33
vipermagi писал(а):
22.08.2013 17:08
Значит, чтобы получить доступ к адресу следующего байта, надо сделать приведение к void* ?

Да. Или к char *.

Лучше к uint8_t/int8_t из C99 stdint.h. char это все-таки символьный тип :)

drBatty писал(а):
23.08.2013 00:37
А вот размер _указателя_ void* вполне определён, правда только во время компиляции (на другой архитектуре он будет другим).

Собственно как и любой другой указатель.
Спасибо сказали:

Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: C: массив указателей

Сообщение drBatty »

BratSinot писал(а):
06.09.2013 14:21
Лучше к uint8_t/int8_t из C99 stdint.h. char это все-таки символьный тип

согласен. Лучше. А то ведь char может быть и многобайтовым на некоторых платформах(правда на них AFAIK понятие "следующий байт" вообще лишено смысла, ибо CPU тупо не умеет к памяти побайтно обращаться, потому и char такой нестандартный. Но всё равно)
BratSinot писал(а):
06.09.2013 14:21
А вот размер _указателя_ void* вполне определён, правда только во время компиляции (на другой архитектуре он будет другим).
Собственно как и любой другой указатель.

очевидно да. Я надеюсь для ТСа это теперь тоже очевидно. А то он раньше путал размер указателя с тем, на что этот указатель указывает. "Размер void*" например не имеет никакого смысла, ибо void* может указывать на что угодно.
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:

Аватара пользователя
Rootlexx
Бывший модератор
Сообщения: 4417
Статус: GNU generation
ОС: Debian GNU/Linux

Re: C: массив указателей

Сообщение Rootlexx »

BratSinot писал(а):
06.09.2013 14:21
Лучше к uint8_t/int8_t из C99 stdint.h. char это все-таки символьный тип

Прежде всего это целочисленный тип. То, что в нём хранится, зависит исключительно от интерпретации.
drBatty писал(а):
06.09.2013 14:39
А то ведь char может быть и многобайтовым на некоторых платформах(правда на них AFAIK понятие "следующий байт" вообще лишено смысла, ибо CPU тупо не умеет к памяти побайтно обращаться, потому и char такой нестандартный. Но всё равно)

На таких платформах int8_t вообще не определён. Тогда уж int_least8_t. Вот только последний будет определён как signed char, как следует из стандарта (7.18.1.2), так что разницы особой нет.
Спасибо сказали:

NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: C: массив указателей

Сообщение NickLion »

drBatty писал(а):
06.09.2013 14:39
BratSinot писал(а):
06.09.2013 14:21
Лучше к uint8_t/int8_t из C99 stdint.h. char это все-таки символьный тип

согласен. Лучше. А то ведь char может быть и многобайтовым на некоторых платформах(правда на них AFAIK понятие "следующий байт" вообще лишено смысла, ибо CPU тупо не умеет к памяти побайтно обращаться, потому и char такой нестандартный. Но всё равно)

Не может быть char многобайтовым:
(INTERNATIONAL STANDARD ISO/IEC 9899:201x (Стандарт языка Си)) писал(а):Semantics
The sizeof operator yields the size (in bytes) of its operand
...
When sizeof is applied to an operand that has type char, unsigned char, or
signed char, (or a qualified version thereof) the result is 1.

Просто байт может быть не 8-ми битным: не обязательно октет. Байт — минимальная адресуемая единица ведь.
Спасибо сказали:

Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: C: массив указателей

Сообщение drBatty »

Rootlexx писал(а):
06.09.2013 17:41
На таких платформах int8_t вообще не определён.

да.
NickLion писал(а):
06.09.2013 17:52
Не может быть char многобайтовым:

пусть будет "может быть многооктетным". Так вам больше нравится? По моему мнению в 16и битах 2 байта, И это может быть одним char'м.
NickLion писал(а):
06.09.2013 17:52
Просто байт может быть не 8-ми битным: не обязательно октет. Байт — минимальная адресуемая единица ведь.

в классической сишечке это называлось всегда char. Термин 'byte' появился в более поздних редакциях стандарта.

Я же не ленивый...
3.6
byte
addressable unit of data storage large enough to hold any member of the basic character
set of the execution environment
NOTE 1 It is possible to express the address of each individual byte of an object uniquely.

NOTE 2 A byte is composed of a contiguous sequence of bits, the number of which is implementation-defined. The least significant bit is called the low-order bit; the most significant bit is called the high-order bit.
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:

NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: C: массив указателей

Сообщение NickLion »

А если char занимает, к примеру, 12 бит — сколько это байт в Вашем понимании? 1,5? Байт по определению НЕ имеет ровно 8 бит. И sizeof(char)==1 всегда, меньше ничего нет.
Спасибо сказали:

BratSinot
Сообщения: 812
ОС: Slackware64

Re: C: массив указателей

Сообщение BratSinot »

Rootlexx писал(а):
06.09.2013 17:41
На таких платформах int8_t вообще не определён. Тогда уж int_least8_t. Вот только последний будет определён как signed char, как следует из стандарта (7.18.1.2), так что разницы особой нет.

int8_t определен стандартом C99, что он 8 и не больше. А вот int_least8_t, тем-же стандартом, определен не меньше 8, значит может и больше.
Спасибо сказали:

Аватара пользователя
Rootlexx
Бывший модератор
Сообщения: 4417
Статус: GNU generation
ОС: Debian GNU/Linux

Re: C: массив указателей

Сообщение Rootlexx »

BratSinot писал(а):
08.09.2013 21:24
Rootlexx писал(а):
06.09.2013 17:41
На таких платформах int8_t вообще не определён. Тогда уж int_least8_t. Вот только последний будет определён как signed char, как следует из стандарта (7.18.1.2), так что разницы особой нет.

int8_t определен стандартом C99, что он 8 и не больше. А вот int_least8_t, тем-же стандартом, определен не меньше 8, значит может и больше.

И?
Спасибо сказали:

NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: C: массив указателей

Сообщение NickLion »

BratSinot писал(а):
08.09.2013 21:24
int8_t определен стандартом C99, что он 8 и не больше

Да, но если платформа не поддерживает адресацию 8-битных элементов, то int8_t просто не будет определён (7.18.1.1 Exact-width integer types: These types are optional.), а код использующий int8_t не скомпилится. А при использоании char компиляция произойдёт на любой платформе.

BratSinot писал(а):
08.09.2013 21:24
А вот int_least8_t, тем-же стандартом, определен не меньше 8, значит может и больше.

Да, но данный тип определён всегда.
Спасибо сказали:

FlySnake
Сообщения: 992
ОС: openSUSE

Re: C: массив указателей

Сообщение FlySnake »

Немного оффтоп: есть ли в современном реальном мире машины где байт != 8 бит?
Спасибо сказали:

Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: C: массив указателей

Сообщение drBatty »

NickLion писал(а):
08.09.2013 14:50
А если char занимает, к примеру, 12 бит — сколько это байт в Вашем понимании? 1,5?

да.
NickLion писал(а):
08.09.2013 14:50
Байт по определению НЕ имеет ровно 8 бит. И sizeof(char)==1 всегда, меньше ничего нет.

да. да. А вы путаетесь потому, что char != байт. (:

В стандарте "байт" не определён, и является просто названием "минимально адресуемой памяти в большинстве реализаций". А вот char -- вполне определённая штука. Её размер всегда единица. Ну а её размер в байтах/битах -- не определён.

NickLion писал(а):
08.09.2013 22:07
А при использоании char компиляция произойдёт на любой платформе.

это плохо. Если программист думает, что в char'е 8 бит (один "байт" по моему разумению), то быдлокод соберётся, и будет работать неправильно. Это куда как хуже, чем если использовать int8_t, с которым код не соберётся (и не должен).

FlySnake писал(а):
09.09.2013 00:56
Немного оффтоп: есть ли в современном реальном мире машины где байт != 8 бит?

говорят, во многих DSP именно 16 бит во всех типах данных. В т.ч. и в char'е. Ну они с сигналами работают, зачем там октеты? Октет для сигнала слишком мало.
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:

NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: C: массив указателей

Сообщение NickLion »

FlySnake писал(а):
09.09.2013 00:56
Немного оффтоп: есть ли в современном реальном мире машины где байт != 8 бит?

Как уже сказал drBatty вроде есть с 16-битными. Но не сталкивался с таким вживую. А с некратным 8 наверное только в истории остались.

drBatty писал(а):
09.09.2013 07:21
NickLion писал(а):
08.09.2013 14:50
А если char занимает, к примеру, 12 бит — сколько это байт в Вашем понимании? 1,5?

да.

Знаете, 1,5 байта — это мегастранно.

drBatty писал(а):
09.09.2013 07:21
А вы путаетесь потому, что char != байт. (:

В стандарте "байт" не определён, и является просто названием "минимально адресуемой памяти в большинстве реализаций". А вот char -- вполне определённая штука. Её размер всегда единица. Ну а её размер в байтах/битах -- не определён.

Ещё раз, в стандарте языка Си говорится, что sizeof меряет размер информации в байтах и sizeof(char)==1. Char (тип данных) — это не байт (размер данных), но имеет размер один байт.
Более того, байт в стандарте определён:
3.6
byte
addressable unit of data storage large enough to hold any member of the basic character
set of the execution environment
NOTE 1
It is possible to express the address of each individual byte of an object uniquely.
NOTE 2 A byte is composed of a contiguous sequence of bits, the number of which is implementation-
defined. The least significant bit is called the low-order bit; the most significant bit is called the high-order
bit.


drBatty писал(а):
09.09.2013 07:21
это плохо. Если программист думает, что в char'е 8 бит (один "байт" по моему разумению), то быдлокод соберётся, и будет работать неправильно. Это куда как хуже, чем если использовать int8_t, с которым код не соберётся (и не должен).

Плохо то, что он так думает. И да, если нужен тип с ровно 8 битами, то конечно надо использовать int8_t, а не char. А если нужно адресовать память минимальными единицами, то правильнее использовать char.
Спасибо сказали:

Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: C: массив указателей

Сообщение drBatty »

NickLion писал(а):
09.09.2013 09:54
Знаете, 1,5 байта — это мегастранно.

ну 0.375 литров водки в одной бутылке -- тоже мегастранно. Ну и что. Бывает.
Бывают и 1.5 бита.
NickLion писал(а):
09.09.2013 09:54
Плохо то, что он так думает. И да, если нужен тип с ровно 8 битами, то конечно надо использовать int8_t, а не char. А если нужно адресовать память минимальными единицами, то правильнее использовать char.

ну. И при чём тут "байт"? К словам придираетесь? Ну и то, что там выше -- это не определение, а объяснение. К языку это мало относится. В языке есть char, есть int8_t, вот и всё. Никаких "байтов" непосредственно в языке нет.
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:

NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: C: массив указателей

Сообщение NickLion »

Я не придираюсь к словам, а пытаюсь сказать, что в C есть тип данных, к которым относятся char, int8_t, etc. А есть мера информации. Стандарт в качестве такой меры определяет байт. И char занимает 1 байт. Поэтому, хотя непосредственное байтов нет, sizeof работает с байтами, а не с char'ами. Потому что нельзя скзать, что float — это, к примеру, 4 char'а, но можно сказать, что это 4 байта.
Спасибо сказали:

Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: C: массив указателей

Сообщение drBatty »

NickLion
ну всё верно, я лишь хочу подчеркнуть, что лучше говорить "размер float во многих архитектурах составляет 4 char'а". Или просто 4, т.к. sizeof(char)==1 по определению. А вот слово "байт" лучше не упоминать вовсе, ибо оно может быть понято по разному, а следовательно -- неправильно.

И да, информация измеряется вообще говоря "в штуках", это безразмерная величина. Для удобства используется её логарифм, т.е. биты, ниты, и диты. Ну а "байт" штука весьма условная и двусмысленная. Если уж совсем заниматься буквоедством.
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали: