Эквивалентное объявление массивов

Тема в разделе "Общие вопросы по С и С++", создана пользователем gamecreator, 14 ноя 2007.

Статус темы:
Закрыта.
  1. gamecreator

    gamecreator Гость

    а зачем модификатор const для массива?

    European: вопрос возник по поводу передачи указателя на массив в функцию в ЭТОЙ теме
     
  2. European

    Регистрация:
    4 сен 2006
    Сообщения:
    2.580
    Симпатии:
    0
    <!--QuoteBegin-gamecreator+14:11:2007, 15:53 -->
    <span class="vbquote">(gamecreator @ 14:11:2007, 15:53 )</span><!--QuoteEBegin-->а зачем модификатор const для массива?
    [snapback]85688" rel="nofollow" target="_blank[/snapback]​
    [/quote]
    Как зачем? Чтобы гарантировать невозможность изменения элементов массива
     
  3. Blackheart1983

    Blackheart1983 Гость

    //эквивалентное объявление
    mas1( int* );
    mas1( int[] );
    int[ const ] компиль преобразует к виду int*

    при вышенаписанных объявлениях мы можем менять содержимое
    массива а когда вида
    const int* тогда менять не сможем, просто перестраховка от дальнейших ошибок при разработки(привычка)
     
  4. Pasha

    Pasha Гость

    Для: Blackheart1983
    Эквивалентность этих объявлений зависит от компилятора. Например VS не переваривает следующий код:
    Код (Text):
    int m1[5];
    int *m2;
    &m1 == &m2;
    Я не придираюсь, просто забавный факт :)
     
  5. Blackheart1983

    Blackheart1983 Гость

    Так он и не обязан его хавать
    вы пытаетесь сравнить указатель на целое с константым указателем на массив целых как вариант можна воспользоваться указателем void
    или банально сделать указатель на массив из 5 элементов типа int
    компилятор не даст вам сравнить 2 указателя с разными типами данных это сделано намеренно по крайней
    мере в стандарте с++ v6 в "С" не селен спорить не буду
    А на счёт компиля я с вами согласен, каждый разработчик под своим лозунгом на подобие "Cтановитесь в позу зю я любовь свою воньзю"
     
  6. Pasha

    Pasha Гость

    <!--QuoteBegin-Blackheart1983+14:11:2007, 18:48 -->
    <span class="vbquote">(Blackheart1983 @ 14:11:2007, 18:48 )</span><!--QuoteEBegin-->вы пытаетесь сравнить указатель на целое с константым указателем на массив целых как вариант можна
    [snapback]85714" rel="nofollow" target="_blank[/snapback]​
    [/quote]Я пытаюсь сравнить "указатель на указатель на целое" с "указателем на массив целых длиной 5", по крайней мере так это воспринимает майкрософтовский компилятор. Для него int*, int[], int[5] и int[6] - разные типы, mas1( int* ) и mas1( int[] ) - разные объявления. Что как-то расходится с распространенным мнением что массив - это просто константный указатель.

    З.Ы. Что интереснее: флудить на отвлеченные темы или решать элементарные задачи за других? :)
     
  7. Blackheart1983

    Blackheart1983 Гость

    1)Ну как сказать, эквивалентность имелось ввиду как указатель на массив в виде параметра функции а не как объявление масива как такового и тут VS абсолютно ни при чём.
    Ещё раз повторюсь это стандарт с++

    у меня при компиляции вылезла такая ошибка
    ts\main\main\main.cpp(7) : error C2446: '==' : no conversion from 'int ***__w64 ' to 'int (*__w64 )[5]'
    Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style
    cast

    Ну и наконец майкрософт в своих логике не гениален и допустить ошибку тоже мог. по логике этого сообщения вообще фиг создашь указатель на такую структуру попросту не заработает но если верить стандарту с++ то код будет приблизительно иметь следующий вид и при том будет работать ещу раз повторюсь передача указателя на 0-й эл массива как параметр функции это не совсем то как создание локально самого массива попробуйте создать как параметр и всё у вас получится я перепроверил
    Ну не верите мне возьмите книгу напр. Липмана 3-й том там это довольно якро разписуется (Не в обиду будет сказано)
    #include <iostream>
    int main(int argc,char *argv[])
    {
    int m1[5];
    int *m2=&m1[0];//указатель на целое и берём адрес целого
    typedef int mas[5] ;
    typedef mas (*pmas);
    pmas o;//это и будет указатель на массив
    o=&m1;
    if(&m1 == o)
    std::cout<<"address is right compare is ok";
    if(&m1[0]==m2)
    std::cout<<"compare is ok";
    return NULL;
    }
    А то что пи...т VS при компиляции так это не мне
    вам разсказывать, он и не такое скажет :)
    2) насчёт флуда, какой же это флуд задание написано и реализовано затронулся вопрос притом тематический :)
     
  8. Pasha

    Pasha Гость

    <!--QuoteBegin-Blackheart1983+14:11:2007, 22:53 -->
    <span class="vbquote">(Blackheart1983 @ 14:11:2007, 22:53 )</span><!--QuoteEBegin-->ещу раз повторюсь передача указателя на 0-й эл массива как параметр функции это не совсем то как создание локально самого массива попробуйте создать как параметр и всё у вас получится я перепроверил
    [snapback]85732" rel="nofollow" target="_blank[/snapback]​
    [/quote]Да я как бы и не спорю, просто забавно что тип локальной переменной int m[] не совпадает с типом параметра int m[]; хотя в стандарте описывается одной и той же статьей.
     
  9. gamecreator

    gamecreator Гость

    странно что при int m1[5], *m2;
    &m1==&m2 вызывает ошибку, тогда как m1==m2 компилируется.
     
  10. Blackheart1983

    Blackheart1983 Гость

    а чего тут странного
    идёт сравнение двух адресов целого типа

    using namespace std;
    int m1[5], *m2;
    m1[0]=200;
    cout<<m1<<endl<<&m1[0];
    cin>>m1[0];

    разберите исходник что я написал выше должно стать понятно почему
    а лучше скачайте книгу Липмана
    как по мне то лучшая книга по с++ страустроп отдыхает, хотя начинающий программер
    врят ли её потянет я в своё время прошёл с 3-го раза :)
    http://rapidshare.com/files/69836366/Lippman_rus.rar.html
    хотел выложить в раздел книги да тема закрыта
     
  11. European

    Регистрация:
    4 сен 2006
    Сообщения:
    2.580
    Симпатии:
    0
    <!--QuoteBegin-Blackheart1983+15:11:2007, 14:39 -->
    <span class="vbquote">(Blackheart1983 @ 15:11:2007, 14:39 )</span><!--QuoteEBegin-->хотел выложить в раздел книги да тема закрыта
    [snapback]85874" rel="nofollow" target="_blank[/snapback]​
    [/quote]
    Разве? Ты куда выкладывал? Надо сюда: http://codeby.net/forum/threads/14324.html
     
  12. Blackheart1983

    Blackheart1983 Гость

    нажимаю на кнопку "ответить" или "новая тема" пишет нету прав
    если не сложно бросте туда ссылку на книгу
     
  13. Pasha

    Pasha Гость

    Для: gamecreator
    У типа int[5] есть implicit преобразование к int*, оно возвращает указатель на нулевой элемент. Поэтому m1==m2 компилируется.
    Для: Blackheart1983
    Липман это круто, но начинающий программер, глядя на этот код думает примерно следующее "массив - это константный указатель на нулевой элемент массива, поэтому cout<<m1 выводит адрес нулевого элемента.". На самом деле - массив, объявленый локально, - это переменная типа тип-элементов[длина], с implicit преобразованием в указатель на тип-элементов. Отличие от константного указателя хотя в бы в том, что массив - не l-value. А массив, объявленый с использованием того же синтаксиса, но как параметр функции - это просто указатель.
    Например, следующий код выводит одинаковае значения, но никто не сомневается что типы разные:
    Код (Text):
        int i = 5;
    long l = i;
    cout << i << endl << l << endl;
    Т.е. в случае с long и int для всех очевидно, что происходит implicit conversion. А в случае с массивами никто не догадывается, что происходит implicit conversion. :blink:
     
  14. Pasha

    Pasha Гость

    Можно загадки на собеседовании задавать. Типа, сколько тут будет сгенерено реализаций функции f:
    Код (Text):
    template<typename T> void f(T t) {}
    ...
    void test(int m3[])
    {
    int m1[5];
    int *m2 = m1;
    f(&m1);
    f(&m2);
    f(&m3);
    }
     
  15. Blackheart1983

    Blackheart1983 Гость

    1)Ну и каким чудом тут оказалось неявное преобразование? ну есть неявное преобразование есть явное ну и что давайте ещё с точки зрения асма копнём я могу! разве это меняет суть вопроса?
    вопрос звучал не как компиль реализует ту или иную задачу а в соблюдении стандарта с++ VS
    понятно что я могу целому присвоить с плав. запятой с потерей точности и т.д. разве это меняет суть дела?
    Почитайте внимательней из за чего возник вопрос
    я не сомневаюсь в вашей квалификации, ну так а кто спорил :blink: или всё таки надо было расписывать как только что сделали вы?
    мне уже стремно писать в этой ветке модератор еще разозлится и забанит, если будет интересно
    на эту тему пообщаться пишите в личку
     
  16. European

    Регистрация:
    4 сен 2006
    Сообщения:
    2.580
    Симпатии:
    0
    <!--QuoteBegin-Blackheart1983+15:11:2007, 16:25 -->
    <span class="vbquote">(Blackheart1983 @ 15:11:2007, 16:25 )</span><!--QuoteEBegin-->мне уже стремно писать в этой ветке модератор еще разозлится и забанит, если будет интересно
    на эту тему пообщаться пишите в личку
    [snapback]85905" rel="nofollow" target="_blank[/snapback]​
    [/quote]
    Перенес сообщения в отдельную тему, так что давайте продолжим обсуждение здесь
     
  17. Pasha

    Pasha Гость

    <!--QuoteBegin-Blackheart1983+15:11:2007, 16:25 -->
    <span class="vbquote">(Blackheart1983 @ 15:11:2007, 16:25 )</span><!--QuoteEBegin-->вопрос звучал не как компиль реализует ту или иную задачу а в соблюдении стандарта с++ VS
    [snapback]85905" rel="nofollow" target="_blank[/snapback]​
    [/quote]Собственно мне и было интересно, что есть массивы с точки зрения стандарта С++.
    Текст стандарта: http://plumber.gnu-darwin.org/home/pub/iso...++-standard.pdf
    По стандарту массивы - это совершенно отдельный тип (8.4.3 Arrays), явно привязанный к типу элементов, размерности и к длине массива. А преобразование его к указателю отдельно упоминается в в 4.2. Array-to-pointer conversion. Так что VS соблюдает стандарт.
     
  18. Blackheart1983

    Blackheart1983 Гость

    Ок давайте рассмотрим пример
    массив, объявленый локально, - это переменная типа тип-элементов[длина], с implicit преобразованием в указатель на тип-элементов:

    Эквивалентно то что вы сказали
    коду который я написал выше:
    typedef int mas[5] ;
    typedef mas (*pmas);
    pmas o;
    по вашему что делает компиль...

    второе параметр функции
    который просто указатель //это так и есть вопрос к какому типу и с каким преобразованием он его отнесёт ну для примера если я не буду передавать ему адресс массива с целыми а эдак передам просто указатель на целое.....
    void test(int*a)
    {
    std::cout<<a;//работает чудно не матерится
    std::cout<<a[5];//работает тоже чудно и тоже не матерится. но!!!! Access Violation в случае целого обеспеченно
    //и в случае когда выход за предел массива
    }

    int main(int argc,char *argv[])
    {
    using namespace std;
    int *g=0;
    int g2[6];
    test(g2);
    test(g);
    }
    при компиляции по вашему к какому виду преобразует код компилятор?
    и почему мы пишем test(g2); а не test(&g2);
    Отвечу
    При компиляции компиль не производит проверку на передачу массива это факт
    почему же не передать &g2?
    ну и напоследок разве может константный указатель выступать в виде L-value раз ве что во время инициализации как и массив и конст указатель может аддресовать как переменную не const так и const

    А на счёт соблюдения стандарта я так и написал что всё ок, пока....
     
  19. Blackheart1983

    Blackheart1983 Гость

    Ссылка не работает
    если не трудно сбросьте рабочую мне интересно почитать для самообразования
     
  20. Pasha

    Pasha Гость

    <!--QuoteBegin-Blackheart1983+15:11:2007, 17:36 -->
    <span class="vbquote">(Blackheart1983 @ 15:11:2007, 17:36 )</span><!--QuoteEBegin-->void test(int*a)
    {
    std::cout<<a;//работает чудно не матерится
    std::cout<<a[5];//работает тоже чудно и тоже не матерится. но!!!! Access Violation в случае целого обеспеченно
    //и в случае когда выход за предел массива
    }
    [snapback]85927" rel="nofollow" target="_blank[/snapback]​
    [/quote]Как параметр передается указатель, и работаешь ты с ним как с указателем. Все корректно, потому и компилируется.
    <!--QuoteBegin-Blackheart1983+15:11:2007, 17:36 -->
    <span class="vbquote">(Blackheart1983 @ 15:11:2007, 17:36 )</span><!--QuoteEBegin-->При компиляции компиль не производит проверку на передачу массива это факт
    почему же не передать &g2?
    [snapback]85927" rel="nofollow" target="_blank[/snapback]​
    [/quote]Потому что g2 из int[6] неявно преобразуется в int* при вызове test. Ссылку или указатель на массив в функцию вообще передать нельзя, это спецально оговорено в стандарте, в разделе functions. И проверяется компилятором. Поэтому &g2 передать не получится. В этом и есть фишка массивов. Синтаксически, массив - отдельная переменная. Но при компиляции она везде явно подставляется в виде своего значения. Да еще и опреатор & для массива работает непредсказуемо, т.к. после компиляции переменной как таковой нет:
    Код (Text):
    int m[5];
    const int* p = m;
    std::cout << ((void*)&m == (void*)m) << std::endl; // 1
    std::cout << ((void*)&p == (void*)p) << std::endl; // 0
    Массив - не l-value, к нему вообще нельзя применять &, но та же VS этот код почему-то проглатывает.
    <!--QuoteBegin-Blackheart1983+15:11:2007, 17:36 -->
    <span class="vbquote">(Blackheart1983 @ 15:11:2007, 17:36 )</span><!--QuoteEBegin-->разве может константный указатель выступать в виде L-value раз ве что во время инициализации
    [snapback]85927" rel="nofollow" target="_blank[/snapback]​
    [/quote]Константный указатель - это unmodifiable l-value.


    Для: Blackheart1983
    h_ttp://plumber.gnu-darwin.org/home/pub/isoiec14882-c++-standard.pdf
    Огромный и бесполезный документ для всех, кроме авторов компиляторов :)
     
Загрузка...
Похожие Темы - Эквивалентное объявление массивов
  1. AlexandrJava
    Ответов:
    0
    Просмотров:
    184
  2. bobo
    Ответов:
    1
    Просмотров:
    2.952
  3. sum44
    Ответов:
    2
    Просмотров:
    2.401
Статус темы:
Закрыта.

Поделиться этой страницей