![]() |
|
Модераторы: Daevaorn |
![]()
|
|
| Волод |
|
|||
|
Unregistered |
Помогите разобраться с массивом!
Предположим, у меня есть такой массив строк:
Началось все с того, что я захотел получить через формулу количесво элементов такого массива. Сбацал нечто вроде такого: int elem=(int)(sizeof(li)/sizeof(li[0])). В общем-то количество элементов подсчиталось правильно, но появились подозрения, что полученный таким образом результат будет не всегда верным. Главным образом потому, что мне непонятен механизм выделения памяти под каждую строку в массиве. Если предположить, что на каждую строку память выделяется по числу символов в строку, тогда результат в большинстве случаев будет неверным. Попробовал проверить догадку, оставивив в первой строке всего один символ. – но нет результат расчитался вновь правильно. Тогда я в отладчике посмотрел, сколько памяти выделено под первую строку – и очень удивился - независимо от размера строки оператор sizeof(li[0]) всегда дает 4 байта. То есть для строки “струйкой” это очень мало (на каждый char - символ должен выделяться 1 байт), а для строки из одного символа это очень много. Короче, здесь я окончательно запутался…. Помогите понять механизм выделения памяти под массив строк! И является-ли верным мой вариант поддсчета количества строк, или он срабатывает не всегда… |
|||
|
||||
| chaos |
|
|||
![]() Серийный программист ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2979 Регистрация: 7.7.2004 Где: Екатеринбург Репутация: 6 Всего: 44 |
ты наверное видел не размер выделяемый под строку, а размер для хранения адреса в памяти для этой строки
|
|||
|
||||
| Дрон |
|
|||
![]() Java-ненавистник :) ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 3179 Регистрация: 29.12.2002 Где: Санкт-Петербург Репутация: 10 Всего: 93 |
Волод
Вариант твой верный Си строки действительно несколько хитры. sizeof(li[0]) равно 4, потому что li[0] это указатель (тип char*). И размер указателя (грубо говоря) всегда 4 байта. В Си нет типа строка, на самом деле строка в Си представляет собой просто массив. Если написать: char *str = "abcdef"; то будет создан указатель, значение которого будет адресом в памяти, где хранится сама строка. Сама строка, кстати, будет занимать 7 байт: шесть символов и нулевой байт - конец строки. В твоём коде создаётся массив из 14 указателей, каждый из которых указывает на кусок памяти содержащий символы нужной строки. ЗЫ: Как приятно читать вопрос человека, понимающего что он спрашивает... Сейчас это редкость -------------------- Да. Именно так. |
|||
|
||||
| chaos |
|
|||
![]() Серийный программист ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2979 Регистрация: 7.7.2004 Где: Екатеринбург Репутация: 6 Всего: 44 |
так ты же и так знаешь размер массива на этапе разработке
|
|||
|
||||
| Дрон |
|
|||
![]() Java-ненавистник :) ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 3179 Регистрация: 29.12.2002 Где: Санкт-Петербург Репутация: 10 Всего: 93 |
И где в приведённом коде можно увидеть размер массива? -------------------- Да. Именно так. |
|||
|
||||
| srd |
|
|||
![]() Нереварин ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 951 Регистрация: 30.8.2003 Где: Владивосток Репутация: 27 Всего: 49 |
Извиняюсь, что не совсем по теме, но:
Этот код содержит ошибку. Символьные литералы в Си++ имеют тип const char *, не char *. Возможность присваивать указатели на const char* указателям на char* без явного приведения типов оставлена только для совместимости со старым Си-кодом. Запись в область памяти, занятую символьными литералами, можно разрешить ключиками компилятора, но по умолчанию она должна быть запрещена в любом вменяемом компиляторе. Я однажды обжёгся об это при портировании старой DOS-программы и потому обращаю ваше внимание -------------------- Не смей читать мою подпись!!! |
|||
|
||||
| comcon1 |
|
||||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 838 Регистрация: 11.6.2005 Где: Москва ДАС-МГУ Репутация: 12 Всего: 17 |
Я обычно массивы указателей на объекты, строки и пр. принудительно заканчиваю NULL-ом.
Тогда можно написать функцию (универсальную), получающую размер твоего массива. Типа такой:
Так потом, если ты даже не обрубаешь NULL на конце, компилятор делает это автоматически. Например вот такое работает (у меня GCC):
Выводит десять раз Hellow и NULL в конце |
||||
|
|||||
| Волод |
|
|||
|
Unregistered |
Спасибо за подробные объяснения!
|
|||
|
||||
| chaos |
|
||||
![]() Серийный программист ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2979 Регистрация: 7.7.2004 Где: Екатеринбург Репутация: 6 Всего: 44 |
ручками посчитать |
||||
|
|||||
| Гость_Илья |
|
||||
|
Unregistered |
comcon1, Я запустил твой код который в конце выводит нулл.
У меня компилятор MinGW 3.4.2-20040916-1. Он когда создает массив указателей все их значения мусорные а не нулл, и соответственно возникает ошибка когда он пытается написать элемент по непонятному адресу. Может ты какие нить ключи особенные используешь при компиляции ? И еще, вот так он ругается
А когда скобки убираешь полный порядок
Не подскажете почему так ? |
||||
|
|||||
| Mayk |
|
||||
![]() ^аВаТаР^ сообщение>> ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 2616 Регистрация: 22.5.2005 Где: за границей разум а Репутация: 45 Всего: 134 |
Инициализация новой переменной в ноль в большинстве случаев лишена всякого смысла. Если переменную выделяют, то ее обычно еще в что-то устанавливают. Поэтому если бы новые переменные ставились в 0, то это было бы тратой драгоценного времени. Если хочешь занулить массив разом, то используй
где sizeof_array - кол-во занимаемых массивом байт. -------------------- Здесь был кролик. Но его убили. Человеки < кроликов, йа считаю. |
||||
|
|||||
![]()
|
| Правила форума "С++:Общие вопросы" | |
|
|
Добро пожаловать!
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | C/C++: Общие вопросы | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |