Вопрос про массив строк и указатели

Тема в разделе "Arduino & Shields", создана пользователем DrProg, 1 июл 2015.

  1. Unixon

    Unixon Оракул Модератор

    Что-нибудь про оператор [], указатели и динамическое выделение памяти.
     
  2. geher

    geher Гуру

    Похоже, возникло некоторое терминологическое разногласие.
    Одни считают, что все, к чему можно обратиться как
    Код (Text):
    x[i][j]
    - есмь двумерный массив.
    Другие (включая меня) полагают, что надо зрить в корень, в смысле в распределение памяти.
     
  3. Unixon

    Unixon Оракул Модератор

    Первый оператор [] возвращает адрес начала строки из статического массива элементов типа char*, второй оператор [] разыменовывает этот указатель и обращается к памяти как к одномерному массиву char по адресу начала строки + смещение.
    pointer = start + offset = start + index*sizeof(element);
     
    ИгорьК нравится это.
  4. ИгорьК

    ИгорьК Гуру

    :(
     
  5. ИгорьК

    ИгорьК Гуру

    Что-нибудь про оператор [] я почитаю, но сказанное здесь и так понятно.
    В результате, все это очень похоже, скорее, на трюк (коих в С немало).
    Вы так и не ответили, прав я или нет:
    Код (Text):
    char* myStrings[]={"This is string 1", "This is string 2", "This is string 3",
    "This is string 4", "This is string 5","This is string 6"};
    рождает одномерный массив (последовательную запись) двухбайтных указателей и одновременно строковые массивы(строки), расположенные где-то (возможно и последовательно) в памяти?
    Если строки одинаковой длинны, ясное дело, - можно обращаться к отдельным "ячейкам" строки по адресам, как в Вашем примере, и такое совершенно не возможно, если строки разной длинны.
    Но, запись:
    char* myStrings[]={"This is string 1", "This is string 2", "This is string 3", "This is string 4", "This is string 5","This is string 6"};
    не требует равной длинны строк.
    Тогда почему Ваш код (в общем случае) должен быть разумным, хотя и действительно возможным при некоторых условиях? Кажется, что это делается для ускорения доступа, который по указателям всегда быстрее .
    И при чем здесь динамическое выделение памяти?
     
  6. Unixon

    Unixon Оракул Модератор

    Да.

    Можно и так и так, просто за границами доступной памяти нужно смотреть.

    При том, что с точки зрения языка C это практически ничем не отличатся от динамического массива (двумерного).
     
    DrProg нравится это.
  7. ИгорьК

    ИгорьК Гуру

    Сути явления, но не языка. Язык нас отсылает к malloc etc.
     
  8. DrProg

    DrProg Вечный нерд

    И все же, правильно ли я понимаю, что в начальном примере сам массив символов заполняется разделяющими нулями, вычисляются и запоминаются адреса (указатели) начал строк и так далее компилятором. То есть массив указателей формируется при компиляции программы. И потому элементы массива, соответственно, не могут быть изменены по ходу работы (без ущерба работоспособности).
    Иными словами, запись вида
    Код (Text):
    char* myStrings[]={"This is string 1", "This is string 2", "This is string 3",
    "This is string 4", "This is string 5","This is string 6"};
    может быть определена лишь единожды при инициализации, равно как и прочие массивы любой размерности.
     
  9. Unixon

    Unixon Оракул Модератор

    Не совсем. Каждая строковая константа в отдельности превращается в "null-terminated C string" в памяти. Строки в таком массиве в принципе могут и не располагаться в памяти друг за другом, хотя при объявлении статического массива это скорее всего будет так. Здесь вообще-то просто массив строк, он не константный даже, можно даже переписать строки, главное за выделенную память не высовываться.
     
  10. n_iger

    n_iger Нуб

    С точки зрения компилятора массив суть структура из адреса начального элемента, длины этого элемента и количества таких элементов ПОСЛЕДОВАТЕЛЬНО РАСПОЛОЖЕННЫХ В ПАМЯТИ.
    Структура из адреса переменной и ее длины составляет УКАЗАТЕЛЬ на эту переменную. (Если длину обнулить, т.е. оставить один адрес, то получим указатель на void).
    Таким образом, с точки зрения компилятора, массив -- указатель на начальную переменную и количество таких переменных.
    В случае символьных переменных строка суть массив символов и уже является указателем. поэтому вы и можете создать массив строк разной длины, инициализируя массив указателей на их начало.
    Поэтому, например, мы пишем

    char string[16];
    int num;
    scanf ("%s%d", string,&num);

    В имени строки уже содержится ее адрес, а для целочисленной переменной его следует вычислить.
    Ровно тем же объясняются особенности манипуляций с массивами и указателями.