Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / C++ Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2 3 4 5 6 7 8 9 10 .. 21   вперед  Ctrl
 Си и массив как аргумент функции  [new]
petrav
Member

Откуда:
Сообщений: 2118
Тут пришлось с Си (не С++) поработать. Правильно ли, что вот это вот для компилятора эквивалентно?

void foo(int a[3]);
void foo(int *a);

Т.е. первая функция на самом деле видится компилятором как вторая? И по сути "int a[3]" только человек может прочитать, а компилятор тут видит "int *a"?

Сообщение было отредактировано: 14 май 20, 15:42
14 май 20, 15:40    [22132991]     Ответить | Цитировать Сообщить модератору
 Re: Си и массив как аргумент функции  [new]
mini.weblab
Member

Откуда:
Сообщений: 824
petrav,

не верно:
в первом случае вы передаете целое число а[3] (из некоторого массива а)
во втором показатель на целое число

по-видимому, в первом случае вы имели ввиду int a[], тогда имело бы смысл говорить об эквивалентности.
14 май 20, 16:29    [22133049]     Ответить | Цитировать Сообщить модератору
 Re: Си и массив как аргумент функции  [new]
mayton
Member

Откуда: loopback
Сообщений: 46600
Я-бы рассмотрел еще многомерные. И varrargs.

Сообщение было отредактировано: 14 май 20, 16:33
14 май 20, 16:35    [22133055]     Ответить | Цитировать Сообщить модератору
 Re: Си и массив как аргумент функции  [new]
petrav
Member

Откуда:
Сообщений: 2118
mini.weblab

в первом случае вы передаете целое число а[3] (из некоторого массива а)
во втором показатель на целое число

Чё?

mini.weblab
по-видимому, в первом случае вы имели ввиду int a[]

Нет.
14 май 20, 16:44    [22133061]     Ответить | Цитировать Сообщить модератору
 Re: Си и массив как аргумент функции  [new]
mini.weblab
Member

Откуда:
Сообщений: 824
mini.weblab
petrav,
void foo(int a[3]);
в первом случае вы передаете целое число а[3] (из некоторого массива а)
.

здесь я неправа,

в мануале передают массив так
void foo(int *а);
void foo(int a[]);
14 май 20, 16:51    [22133069]     Ответить | Цитировать Сообщить модератору
 Re: Си и массив как аргумент функции  [new]
Anatoly Moskovsky
Member

Откуда: Odessa
Сообщений: 6494
petrav
Т.е. первая функция на самом деле видится компилятором как вторая? И по сути "int a[3]" только человек может прочитать, а компилятор тут видит "int *a"?

Да.
14 май 20, 17:09    [22133088]     Ответить | Цитировать Сообщить модератору
 Re: Си и массив как аргумент функции  [new]
mini.weblab
Member

Откуда:
Сообщений: 824
petrav,
1.
я думаю, что все зависит от реализации конкретного компилятора

2.
по Кернигану-Ричи, когда речь идет о массиве, все три выражения эквивалентны
автор
Parameter declaration:
So as far as f is concerned, the fact that the parameter refers to part of a larger array is of no consequence.
...
Of course, it is illegal to refer to objects that are not within the array bounds.

f - обозначение декларируемой функции: f(int *arr), f(int arr[])


void foo(int a[]);
void foo(int a[3]);
void foo(int *a);


3.
В общем случае выражения не будут эквивалентными, т.к. выражении void foo(int *a) будет более общим,
как доказательство предложу рассмотреть отсутствие ограничения на количество элементов массива

Сообщение было отредактировано: 14 май 20, 17:21
14 май 20, 17:19    [22133103]     Ответить | Цитировать Сообщить модератору
 Re: Си и массив как аргумент функции  [new]
petrav
Member

Откуда:
Сообщений: 2118
mini.weblab


void foo(int a[]);
void foo(int a[3]);
void foo(int *a);


3.
В общем случае выражения не будут эквивалентными, т.к. выражении void foo(int *a) будет более общим,
как доказательство предложу рассмотреть отсутствие ограничения на количество элементов массива

Ну вот у меня в Студии (компилятор Си) в функцию "void foo(int a[3])" подставляется и NULL, и массив из 5-ти элементов, и простой указатель на int. И всё без единого варнинга. Во язык, я понимаю. :) Простой и ясный.
14 май 20, 17:24    [22133108]     Ответить | Цитировать Сообщить модератору
 Re: Си и массив как аргумент функции  [new]
mayton
Member

Откуда: loopback
Сообщений: 46600
petrav
mini.weblab


void foo(int a[]);
void foo(int a[3]);
void foo(int *a);


3.
В общем случае выражения не будут эквивалентными, т.к. выражении void foo(int *a) будет более общим,
как доказательство предложу рассмотреть отсутствие ограничения на количество элементов массива

Ну вот у меня в Студии (компилятор Си) в функцию "void foo(int a[3])" подставляется и NULL, и массив из 5-ти элементов, и простой указатель на int. И всё без единого варнинга. Во язык, я понимаю. :) Простой и ясный.

Это то о чем я говорил. Чортов компиллятор может 80% потенциальных граблей отбросить без этих ПВС-студий
еще в фазе компилляции.
14 май 20, 17:32    [22133119]     Ответить | Цитировать Сообщить модератору
 Re: Си и массив как аргумент функции  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 50076

mayton
Чортов компиллятор может 80% потенциальных граблей отбросить без этих ПВС-студий
еще в фазе компилляции.

Может. Но не хочет. Вместо этого почему-то подменяет написанное "передать массив трёх
целых по значению" на "передать указатель на любой массив".

Posted via ActualForum NNTP Server 1.5

14 май 20, 17:42    [22133130]     Ответить | Цитировать Сообщить модератору
 Re: Си и массив как аргумент функции  [new]
petrav
Member

Откуда:
Сообщений: 2118
Dimitry Sibiryakov

mayton
Чортов компиллятор может 80% потенциальных граблей отбросить без этих ПВС-студий
еще в фазе компилляции.

Может. Но не хочет. Вместо этого почему-то подменяет написанное "передать массив трёх
целых по значению" на "передать указатель на любой массив".

Потому что так в стандарте написано. Я вспомнил, где-то читал, то ли у Керниган & Ритчи, то ли у Страуструпа, что вот такое "int a[3]" в сигнатуре функции -- это просто подсказка для человека. Но на самом деле там "int *a". Компилятор тут бессилен. Он даже варнинг тут выдать не может.

А массивы в Си не передаются по значению и тоже по стандарту. Хотя это косяк из-за не симметрии. Структуры же передаются по значению. У них была странная аргументация: массивы не передаются по значению, что бы из-за ошибки программиста не просадить производительность приложения.
14 май 20, 17:51    [22133138]     Ответить | Цитировать Сообщить модератору
 Re: Си и массив как аргумент функции  [new]
mini.weblab
Member

Откуда:
Сообщений: 824
:)
#include <stdio.h>

void print_arr(int arr[3]) {
    for (int i=0; i<1000; i++) {
        printf("%d, %d\n", i, arr[i]);
    }
}

void main() {
    int arr[] = {0};
    int *a;
    a = &arr[0];
    print_arr(arr);
    for (int i=0; i<1000; i++) {
        printf("%d, %d\n", i, *(a+i));
    }
    printf("\n");
}
14 май 20, 17:53    [22133139]     Ответить | Цитировать Сообщить модератору
 Re: Си и массив как аргумент функции  [new]
Dima T
Member

Откуда:
Сообщений: 14760
petrav
Ну вот у меня в Студии ... И всё без единого варнинга. Во язык, я понимаю. :) Простой и ясный.

Студия много на себя берет и не предупреждает там где стоило бы. Для начала подними уровень ворнингов на максимальный, это где-то в свойствах проекта.

По теме: массив и указатель одно и тоже, передать массив в параметрах нельзя, но передавая массив как указатель размер массива не передается. В шаблонах С++ можно передать массив как массив, но тогда для каждой размерности массива компилируется отдельная функция.
14 май 20, 18:35    [22133188]     Ответить | Цитировать Сообщить модератору
 Re: Си и массив как аргумент функции  [new]
mini.weblab
Member

Откуда:
Сообщений: 824
#include <stdio.h>

void main() {
    int arr[] = {0, 1, 2, 3, 4, 5};
    int *a;
    a = arr;
    int size_of_ptr_a = sizeof(a);
    int size_of_arr = sizeof(arr);

    printf("%d, %d\n", size_of_ptr_a, size_of_arr);
}
14 май 20, 18:43    [22133195]     Ответить | Цитировать Сообщить модератору
 Re: Си и массив как аргумент функции  [new]
petrav
Member

Откуда:
Сообщений: 2118
Dima T
petrav
Ну вот у меня в Студии ... И всё без единого варнинга. Во язык, я понимаю. :) Простой и ясный.

Студия много на себя берет и не предупреждает там где стоило бы. Для начала подними уровень ворнингов на максимальный, это где-то в свойствах проекта.

Уровень предупреждений стоит на оптимальном значении -- 3. Выше начинают сыпаться предупреждения на сторонние библиотеки. Даже на Windows.h. Я не знаю как их отфильтровать.

Dima T
По теме: массив и указатель одно и тоже, передать массив в параметрах нельзя, но передавая массив как указатель размер массива не передается. В шаблонах С++ можно передать массив как массив, но тогда для каждой размерности массива компилируется отдельная функция.

Тут другое хуже. Вот так может быть только в заголовочных файлах (исключая вариант если шаблонный метод вызывается только внутри реализации класса):

template <size_t N>
void foo(int (&a)[N]) {}

А external templates они так и не реализовали почему-то. Вот что мешало?
14 май 20, 18:49    [22133205]     Ответить | Цитировать Сообщить модератору
 Re: Си и массив как аргумент функции  [new]
Dima T
Member

Откуда:
Сообщений: 14760
petrav
А external templates они так и не реализовали почему-то. Вот что мешало?

Такие шаблоны сами по себе зло.

Не надо путать массивы С с массивами С# или Java. Аналог в C++ тех массивов класс std::vector, используй его.

Если хочется передать именно массив С, то передаешь указатель и размер, т.е.
void foo(int *a, size_t size);


Сообщение было отредактировано: 14 май 20, 18:57
14 май 20, 18:55    [22133208]     Ответить | Цитировать Сообщить модератору
 Re: Си и массив как аргумент функции  [new]
Dima T
Member

Откуда:
Сообщений: 14760
petrav
А external templates они так и не реализовали почему-то. Вот что мешало?

А мешало то что под каждый размер компилируется отдельная функция, как ты представляешь заранее скомпилировать size_t функций? Для x64 size_t это 264
14 май 20, 18:57    [22133213]     Ответить | Цитировать Сообщить модератору
 Re: Си и массив как аргумент функции  [new]
mini.weblab
Member

Откуда:
Сообщений: 824
void test_arr() {
    int arr[3] = {1,2,3};
    int n = 10000;

    for ( int i=0; i<n; i++ ) {
        printf("%d, %p, %d\n", i, &arr[i],  arr[i]);
        printf("\n");
    }
}

void test_ptr() {
    int n = 10000;
    int *a;
    *a = 0;

    for ( int i=0; i<n; i++ ) {
        printf("%d, %p, %d\n", i, a+i,  *(a+i));
        printf("\n");
    }
}
14 май 20, 19:00    [22133215]     Ответить | Цитировать Сообщить модератору
 Re: Си и массив как аргумент функции  [new]
petrav
Member

Откуда:
Сообщений: 2118
Dima T
petrav
А external templates они так и не реализовали почему-то. Вот что мешало?

Такие шаблоны сами по себе зло.

Какие такие? External templates зло? Почему?

Dima T
Не надо их путать массивы С с массивами С# или Java. Аналог в C++ тех массивов класс std::vector, используй его.

Если хочется передать именно массив С, то передаешь указатель и размер, т.е.
void foo(int *a, size_t size);

Да я это понимаю. Я вопрос задал для очистки совести. Вдруг совершенно неожиданно тут "void foo(int a[3])" я догадался, что "a == NULL" вполне реально. Поскольку я программирую на С++ были необычные ощущения.
14 май 20, 19:01    [22133216]     Ответить | Цитировать Сообщить модератору
 Re: Си и массив как аргумент функции  [new]
Dima T
Member

Откуда:
Сообщений: 14760
mini.weblab,

хватит откровенный бред постить.
14 май 20, 19:01    [22133217]     Ответить | Цитировать Сообщить модератору
 Re: Си и массив как аргумент функции  [new]
Dima T
Member

Откуда:
Сообщений: 14760
petrav
Какие такие? External templates зло? Почему?

Про External 22133213, а зло потому что под каждый размер скомпилируется отдельная функция. Сто вызовов с разным размером - в конечном коде будет 100 разных функций. 1000 - 1000. И задать размер массива можно только явно до компиляции.
14 май 20, 19:05    [22133225]     Ответить | Цитировать Сообщить модератору
 Re: Си и массив как аргумент функции  [new]
petrav
Member

Откуда:
Сообщений: 2118
Dima T
petrav
А external templates они так и не реализовали почему-то. Вот что мешало?

А мешало то что под каждый размер компилируется отдельная функция, как ты представляешь заранее скомпилировать size_t функций? Для x64 size_t это 264

А как ты себе представляешь в программе руками набить 264 массивов:

char a1[1];
char a1[2];

Что бы для них скомпилировалось 264 шаблонов? Только написав кодогенератор что бы сломать компилятор.

И главное, при чём тут external template?!
14 май 20, 19:07    [22133228]     Ответить | Цитировать Сообщить модератору
 Re: Си и массив как аргумент функции  [new]
petrav
Member

Откуда:
Сообщений: 2118
Dima T
petrav
Какие такие? External templates зло? Почему?

Про External 22133213, а зло потому что под каждый размер скомпилируется отдельная функция. Сто вызовов с разным размером - в конечном коде будет 100 разных функций. 1000 - 1000. И задать размер массива можно только явно до компиляции.

Где тут размер массива?

external template <typename Char>
void drawMyChar(Char);

Может я что-то путаю?
14 май 20, 19:10    [22133232]     Ответить | Цитировать Сообщить модератору
 Re: Си и массив как аргумент функции  [new]
Dima T
Member

Откуда:
Сообщений: 14760
petrav
И главное, при чём тут external template?!

external это значит скомпилировать заранее, например DLL. Как скомпилировать DLL не зная что вызовут?
int a1[5] = ...;
foo(a1);
int a2[100500] = ...;
foo(a2);

Если foo() internal, т.е. код шаблона в .h файле, то будет скомпилировано две функции, а если external то надо заранее иметь все возможные варианты.
14 май 20, 19:11    [22133235]     Ответить | Цитировать Сообщить модератору
 Re: Си и массив как аргумент функции  [new]
mini.weblab
Member

Откуда:
Сообщений: 824
Dima T
... массив и указатель одно и тоже.

неверно! это не бред, это контрпример!
mini.weblab
#include <stdio.h>

void main() {
    int arr[] = {0, 1, 2, 3, 4, 5};
    int *a;
    a = arr;
    int size_of_ptr_a = sizeof(a);
    int size_of_arr = sizeof(arr);

    printf("%d, %d\n", size_of_ptr_a, size_of_arr);
}
14 май 20, 19:15    [22133239]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2 3 4 5 6 7 8 9 10 .. 21   вперед  Ctrl
Все форумы / C++ Ответить