Передать массив из функции
От: Аноним  
Дата: 29.06.10 12:11
Оценка: :))) :))
Привет, необходимо передать массив заданный в функции:
int* myfunc(int *b)
{
int i;
long a[200];

for (i=0;i<200;i++)
a[i]=b[i];
return a;
}
Подскажите, почему возвращаются только первые несколько элементов, как исправить? Заранее спасибо.
Re: Передать массив из функции
От: dabeat_bf Украина http://alexmogurenko.com
Дата: 29.06.10 12:19
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Привет, необходимо передать массив заданный в функции:

А>int* myfunc(int *b)
А>{
А>int i;
А>long a[200];

А>for (i=0;i<200;i++)

А>a[i]=b[i];
А>return a;
А>}
А>Подскажите, почему возвращаются только первые несколько элементов, как исправить? Заранее спасибо.

вообще не особо хорошо чтоб функция возвращала указатель, но если очень хочеться, то:


int * a = new int[200];


P.S. не забудьте вызвать
delete []

для результата функции или получите лик
Re: Передать массив из функции
От: Анатолий Широков СССР  
Дата: 29.06.10 12:22
Оценка: +3

int* myfunc(int *dst, int *src, size_t s)
{
   for(size_t i = 0; i < s; i++)
      dst[i] = src[i];
   return dst;
}

...
int a[200];
int b[200];
myfunc(b, a, s);
Re: Передать массив из функции
От: stapter  
Дата: 29.06.10 13:07
Оценка: 1 (1)
Здравствуйте, Аноним, Вы писали:

А>Привет, необходимо передать массив заданный в функции:

А>int* myfunc(int *b)
А>{
А>int i;
А>long a[200];

А>for (i=0;i<200;i++)

А>a[i]=b[i];
А>return a;
А>}
А>Подскажите, почему возвращаются только первые несколько элементов, как исправить? Заранее спасибо.

Тебе вообще повезло, что программа не завершилась аварийно
Так делать нельзя. Потому что массив "a", выделен на стеке. А что происходит со стеком функции, при выходе из функции? Правильно! Он освобождается, и, таким образом, ты возвращаешь невалидный указатель. Как вариант можешь выделить память в куче, и не забыть ее освободить, чтобы не было утечек. А можешь просто передать указатель на выделенную память, куда ты потом скопируешь массив, как это было продемонстрировано выше.
Re: Передать массив из функции
От: Cris Украина  
Дата: 29.06.10 13:47
Оценка: +1 -3 :)
Здравствуйте, Аноним, Вы писали:

А>Привет, необходимо передать массив заданный в функции:

А>int* myfunc(int *b)
А>{
А>int i;
А>long a[200];

А>for (i=0;i<200;i++)

А>a[i]=b[i];
А>return a;
А>}
А>Подскажите, почему возвращаются только первые несколько элементов, как исправить? Заранее спасибо.
попробуй в функции обьявить массив a как
static long a[200];

он должен оставить массив после завершения функции
Re[2]: Передать массив из функции
От: monax  
Дата: 29.06.10 14:18
Оценка: 1 (1) -1
Здравствуйте, Cris, Вы писали:

C>он должен оставить массив после завершения функции


Нельзя так делать, это глобальная переменная получится.

#include <iostream>

using namespace std;

int* foo() {
    static int a[3];
    for (int i = 0; i < 3; i++) {
        a[i] = i;
    }

    return a;
}

int main() {
    int *a;
    int *b;

    a = foo();

    cout << a[0] << ' ' << a[1] << ' ' << a[2] << endl;

    b = foo();
    cout << b[0] << ' ' << b[1] << ' ' << b[2] << endl;

    a[1] = 100;

    cout << a[0] << ' ' << a[1] << ' ' << a[2] << endl;
    cout << b[0] << ' ' << b[1] << ' ' << b[2] << endl;


    return 0;
}


0 1 2
0
1 2
0 100 2

0 100 2


После такого создания массив нужно копировать. Проще сразу создавать его в выделенной для него памяти и возвращать на него указатель, как предложили выше.
Re[3]: Передать массив из функции
От: dabeat_bf Украина http://alexmogurenko.com
Дата: 29.06.10 14:41
Оценка:
Здравствуйте, monax, Вы писали:
M>Нельзя так делать, это глобальная переменная получится.

явно не глобальная.
Re[4]: Передать массив из функции
От: GhostCoders Россия  
Дата: 29.06.10 14:48
Оценка:
Здравствуйте, dabeat_bf, Вы писали:

_>явно не глобальная.


Переменная не глобальная, но будут ограничения в использовании функции...

int* myfunc(int *b)
{
int i;
static long a[200];

for (i=0;i<200;i++)
a[i]=b[i];
return a;
}

int inputArray[200];
for(int i=0;i<200;i++)
  inputArray[i] = 0;

int result1 = myfunc(inputArray); // Первый раз все OK

int inputArray2[200];
for(int i=0;i<200;i++)
  inputArray2[i] = 1;
int result2 = myfunc(inputArray); // косяк!

// Сейчас result1 и result2
// Указывают на один и тотже массив
// который заполнен единицами
// в массиве result1 тоже все единицы
Третий Рим должен пасть!
Re[5]: Передать массив из функции
От: dabeat_bf Украина http://alexmogurenko.com
Дата: 29.06.10 15:01
Оценка:
Здравствуйте, GhostCoders, Вы писали:

GC>Здравствуйте, dabeat_bf, Вы писали:


_>>явно не глобальная.

GC>Переменная не глобальная, но будут ограничения в использовании функции...

знаю, знаю... но статик имеет право на жизнь, главное понимать что и зачем ты делаешь.
Re: Передать массив из функции
От: rm822 Россия  
Дата: 29.06.10 17:29
Оценка: :)
std::vector<int> myfunc(int *b)
{
  std::vector<int> a; 
  a.resize(200);

  for (int i=0;i<200;i++)
    a[i]=b[i];
  return a;
}
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[2]: Передать массив из функции
От: s.ts  
Дата: 29.06.10 17:30
Оценка:
В общем, нужна оценка типа "компенсировать минусы вставленные посту пока у тебя баллов хватает".
А то получается, что есть возможность только переоценить или недооценить, без учета будующих "оценщиков".
Сложновато, конечно, но иногда хочется
Как пример, пост на который я отвечаю — в качестве ответа на вопрос это не супер, но вполне себе нормальный вариант и минусов по моему явно не заслуживает, но и на плюсы тоже "не полный ответ"

Здравствуйте, Cris, Вы писали:

C>Здравствуйте, Аноним, Вы писали:


А>>Привет, необходимо передать массив заданный в функции:

А>>int* myfunc(int *b)
А>>{
А>>int i;
А>>long a[200];

А>>for (i=0;i<200;i++)

А>>a[i]=b[i];
А>>return a;
А>>}
А>>Подскажите, почему возвращаются только первые несколько элементов, как исправить? Заранее спасибо.
C>попробуй в функции обьявить массив a как
C>
C>static long a[200];
C>

C>он должен оставить массив после завершения функции
Re[6]: Передать массив из функции
От: monax  
Дата: 29.06.10 17:37
Оценка:
Здравствуйте, dabeat_bf, Вы писали:

_>знаю, знаю... но статик имеет право на жизнь, главное понимать что и зачем ты делаешь.


Какие плюсы у статика в этом случае, чтобы мириться с полученными недостатками?
Re[7]: Передать массив из функции
От: s.ts  
Дата: 29.06.10 18:10
Оценка:
Здравствуйте, monax, Вы писали:

M>Здравствуйте, dabeat_bf, Вы писали:


_>>знаю, знаю... но статик имеет право на жизнь, главное понимать что и зачем ты делаешь.


M>Какие плюсы у статика в этом случае, чтобы мириться с полученными недостатками?


сразу скажу, что мы говорим, конечно, про "pure c".
и тут скорее проще поставить вопрос иначе: какие плюсы у других реализаций ?
ответ: только реентерабельность.

т.е. если нет многопоточных вызовов, то static — это хорошее решение.
реентерабельное решение в чистом си сразу влечет дополнительные сложности реализации и использования.
потому многие чисто сишные функции именно так и реализованы — через static.
как-то так.
Re[8]: Передать массив из функции
От: s.ts  
Дата: 29.06.10 18:44
Оценка:
ST>т.е. если нет многопоточных вызовов, то static — это хорошее решение.
ST>реентерабельное решение в чистом си сразу влечет дополнительные сложности реализации и использования.
ST>потому многие чисто сишные функции именно так и реализованы — через static.
ST>как-то так.
да, считаем, что рекурсии тоже нет.
а по поводу массивов на стеке — тут тоже есть нехороший момент, когда они зависят от входных данных.
об этом много написано
Re[9]: Передать массив из функции
От: monax  
Дата: 29.06.10 19:03
Оценка:
Здравствуйте, s.ts, Вы писали:

ST>>сразу скажу, что мы говорим, конечно, про "pure c".

ST>>и тут скорее проще поставить вопрос иначе: какие плюсы у других реализаций ?
ST>>ответ: только реентерабельность.

Я вижу только один плюс использования статика — автоматическое освобождение памяти по окончании работы программы.

ST>>т.е. если нет многопоточных вызовов, то static — это хорошее решение.

ST>>реентерабельное решение в чистом си сразу влечет дополнительные сложности реализации и использования.
ST>>потому многие чисто сишные функции именно так и реализованы — через static.
ST>>как-то так.

ST>да, считаем, что рекурсии тоже нет.


Этих условий изначально не было, ну да ладно, ведь мы же рассматриваем разные ситуации.

В функции у нас создаётся массив. Ожидается, что дважды вызванная функция вернёт два разных массива. Использование статика приводит к возврату указателя на один и тот же массив (я приводил код, который это демонстрирует). Поэтому даже в однопоточной программе у нас есть проблема разделения данных, потому что они для всех общие. Т.е. мы получаем глобальную переменную.

Если у нас "pure c", то можно попробовать делать так:

#include <cstdio>
using namespace std;

#define SIZE 200

struct array {
    int data[SIZE];
};

array foo() {
    array tmp;
    for (int i = 0; i < SIZE; i++) {
        tmp.data[i] = i;
    }
    return tmp;
}

int main() {
    
    array a = foo();
    array b = foo();

    a.data[1] = 10;

    printf("a: %d, b: %d\n", a.data[1], b.data[1]);

    return 0;
}

Вывод программы

a: 10, b: 1


Как видишь, в таком случае у нас нет проблемы общих данных и нет проблемы освобождения памяти. Хотя тут будет расходоваться память при возврате структуры из функции, что плохо при больших SIZE.
Re[10]: Передать массив из функции
От: dabeat_bf Украина http://alexmogurenko.com
Дата: 29.06.10 19:31
Оценка: +1
Здравствуйте, monax, Вы писали:

M>В функции у нас создаётся массив. Ожидается, что дважды вызванная функция вернёт два разных массива. Использование статика приводит к возврату указателя на M>один и тот же массив (я приводил код, который это демонстрирует). Поэтому даже в однопоточной программе у нас есть проблема разделения данных, потому что они M>для всех общие.

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

M>Т.е. мы получаем глобальную переменную.

ну неглобальная это переменная, между статической и глобальной переменной есть большая разница
Re[10]: Передать массив из функции
От: s.ts  
Дата: 29.06.10 20:13
Оценка:
Здравствуйте, monax, Вы писали:

тоже вариант, но это ни "против" ни "в пользу" satic.
просто как вариант.
так что твой минус "статику" все равно трудно объяснить разумно.

P.S.
к слову, код у тебя не сишный.
в деталях, конечно, но все же

M>Если у нас "pure c", то можно попробовать делать так:


M>
M>#include <cstdio>
M>using namespace std;

M>#define SIZE 200

M>struct array {
M>    int data[SIZE];
M>};

M>array foo() {
M>    array tmp;
M>    for (int i = 0; i < SIZE; i++) {
M>        tmp.data[i] = i;
M>    }
M>    return tmp;
M>}

M>int main() {
    
M>    array a = foo();
M>    array b = foo();

M>    a.data[1] = 10;

M>    printf("a: %d, b: %d\n", a.data[1], b.data[1]);

M>    return 0;
M>}
M>

M>Вывод программы
M>

M>a: 10, b: 1


M>Как видишь, в таком случае у нас нет проблемы общих данных и нет проблемы освобождения памяти. Хотя тут будет расходоваться память при возврате структуры из функции, что плохо при больших SIZE.
Re[2]: Передать массив из функции
От: art_kuz Россия  
Дата: 30.06.10 06:30
Оценка:
Здравствуйте, rm822, Вы писали:

R>
R>std::vector<int> myfunc(int *b)
R>{
R>  std::vector<int> a; 
R>  a.resize(200);

R>  for (int i=0;i<200;i++)
R>    a[i]=b[i];
R>  return a;
R>}
R>


супер си-шный вариант
Re[11]: Передать массив из функции
От: monax  
Дата: 30.06.10 08:01
Оценка:
Здравствуйте, s.ts, Вы писали:

ST>так что твой минус "статику" все равно трудно объяснить разумно.


Минус как раз объяснить очень просто. Наведи на него курсор мыши и посмотри на высплывающую подсказку. Там написано "несогласен". Минус я использую именно для этого. Или теперь поставить минус значит что-то иное?

ST>P.S.

ST>к слову, код у тебя не сишный.
ST>в деталях, конечно, но все же

Если заменю array tmp на struct array tmp, ну и инклюды переделаю, тогда будет сишным?
Re[12]: Передать массив из функции
От: s.ts  
Дата: 30.06.10 08:40
Оценка:
Здравствуйте, monax, Вы писали:

ST>>так что твой минус "статику" все равно трудно объяснить разумно.

M>Минус как раз объяснить очень просто. Наведи на него курсор мыши и посмотри на высплывающую подсказку. Там написано "несогласен". Минус я использую именно для этого. Или теперь поставить минус значит что-то иное?

ну, значит не понятно "несогласие" со static

ST>>P.S.

ST>>к слову, код у тебя не сишный.
ST>>в деталях, конечно, но все же

M>Если заменю array tmp на struct array tmp, ну и инклюды переделаю, тогда будет сишным?

что-то типа того.
конечно тут это не принципиально, просто к слову пришлось
Re[2]: Передать массив из функции
От: MasterZiv СССР  
Дата: 30.06.10 15:24
Оценка:
Анатолий Широков wrote:

> int* myfunc(int *dst, const int *src, size_t s)

> {
> for(size_t i = 0; i < s; i++)
> dst[i] = src[i];
> return dst;
> }
Posted via RSDN NNTP Server 2.1 beta
Re: Передать массив из функции
От: meandr  
Дата: 30.06.10 19:25
Оценка:
Передать массив из функцииГрубо говоря массив a был создан в стеке, когда произошел выход из функции стек свернулся и сооветсвенно объект вместе с ним уничтожился и на его месте уже может лежать мусор(а может и не лежать тут уже как карта ляжет), поэтому как тут правильно заметили память нужно выделить динамически, или же вопользоватся STL типами, которые сделают всю работу за нас
Posted via RSDN NNTP Server 2.1 beta
Re[3]: Передать массив из функции
От: gear nuke  
Дата: 01.07.10 02:29
Оценка: :)
Здравствуйте, art_kuz, Вы писали:

_>супер си-шный вариант


Думаешь, такое будет быстрее?
typedef std::array<long, 200> myarray;

myarray myfunc(long*  b)
{
  myarray a;
  for (int i=0;i<200;i++)
    a[i]=b[i];
  return a;
}
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[8]: Передать массив из функции
От: gear nuke  
Дата: 01.07.10 03:02
Оценка: +1
Здравствуйте, s.ts, Вы писали:

ST>сразу скажу, что мы говорим, конечно, про "pure c".

ST>и тут скорее проще поставить вопрос иначе: какие плюсы у других реализаций ?
ST>ответ: только реентерабельность.

Еще и удешевление сопровождения кода. Ужасное количество С кода написано в таком стиле, и для переиспользование приходится передалывать. Код Васи Пупкина можно и не рессматривать, взять старндатную библиотеку С — фукнции вроде gmtime сейчас стали не юзабельны. gmtime_r, или gmtime_s есть не везде. Что далеть то с такими хорошими решениями? Делают даже такие костыли как по отдельному процессу вместо каждого потока

И это еще простая ситуация, когда о проблеме с нереентерабельностью функций заранее известно, а бывает что о таких статиках выясняют после длительного дебага, когда ошибка трудновоспроизводима
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[4]: Передать массив из функции
От: rg45 СССР  
Дата: 01.07.10 03:42
Оценка: +4
Здравствуйте, dabeat_bf, Вы писали:

_>Здравствуйте, monax, Вы писали:

M>>Нельзя так делать, это глобальная переменная получится.

_>явно не глобальная.


Давайте-ка разберемся с тем, что такое "глобальная переменная", потому как ни в C, ни в C++ языках нет такого понятия. А в место этого есть набор свойств, которыми можно характеризовать любую переменную:

В данном случае, массив, объявленный в теле функции с ключевым словом static, является объектом с локальной областью видимости (local scope), статическим классом памяти (static storage duration), без связывания (no linkage).

Теперь давайте решим, какие характеристики являются существенными для нас в данном случае, а какие не очень. По-моему, область видимости и тип связывания нашего массива в данном случае не имеют принципиального значения. А вот область памяти, в которой он расположен, является важной характеристикой. Взвесим все "за" и "против".
Преимущества:
И все.

Недостатки:
С учетом того, что единственное достоинство такого подхода можно достичь массой других способов, ИМХО, вывод в данном случае напрашивается сам собой — это не тот случай, когда использование объектов со статическим временем жизни оправдан.
--
Справедливость выше закона. А человечность выше справедливости.
Re: Передать массив из функции
От: slava_phirsov Россия  
Дата: 02.07.10 09:02
Оценка:
Здравствуйте, Аноним, Вы писали:

Уже было...
Автор: slava_phirsov
Дата: 09.04.10
Люди! Люди, смотрите, я сошел с ума! Люди! Возлюбите друг друга! (вы чувствуете, какой бред?)
Re[2]: Передать массив из функции
От: slava_phirsov Россия  
Дата: 02.07.10 09:07
Оценка:
Здравствуйте, rm822, Вы писали:

R>
R>std::vector<int> myfunc(int *b)
R>{
R>  std::vector<int> a; 
R>  a.resize(200);

R>  for (int i=0;i<200;i++)
R>    a[i]=b[i];
R>  return a;
R>}
R>


Вообще-то у std::vector другие конструкторы есть, помимо explicit vector::vector (const Allocator& = Allocator());
Люди! Люди, смотрите, я сошел с ума! Люди! Возлюбите друг друга! (вы чувствуете, какой бред?)
Re: Передать массив из функции
От: Mak_71_rus Россия  
Дата: 02.07.10 17:27
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Привет, необходимо передать массив заданный в функции:

А>int* myfunc(int *b)
А>{
А>int i;
А>long a[200];

А>for (i=0;i<200;i++)

А>a[i]=b[i];
А>return a;
А>}
А>Подскажите, почему возвращаются только первые несколько элементов, как исправить? Заранее спасибо.

a — это всего лишь указатель на long, а не массив. Вы пытаетесь вернуть локальный массив, т.е. такой память для которого выделяется при входе в функцию и удаляется при выходе из неё. Поэтому нет никакой гарантии, что по указателю, возвращённому из функции находится то, что нужно. Там может находиться всё что угодно!

Для того чтобы решить проблему можно:
1) зарезервировать память под массив в вызывающей функции, а в функцию myfunc передать уназатель на него:

myfunc(int *b, long* a)


2) воспользоваться механизмом динамического резервирования памяти:


long *a = new long[200]


и точно также вернуть
return a;


Теперь есть гарантия того, что, обращаясь по указателю a вы найдёте свой массив. Главное не забудьте его удалить, когда он станет вам не нужен!


delete [] a;


PS: ну чё, народ, вы ржёте? Сами небось по началу над подобным парились.
Re[9]: Передать массив из функции
От: s.ts  
Дата: 05.07.10 01:21
Оценка:
Здравствуйте, gear nuke, Вы писали:

GN>Здравствуйте, s.ts, Вы писали:


ST>>сразу скажу, что мы говорим, конечно, про "pure c".

ST>>и тут скорее проще поставить вопрос иначе: какие плюсы у других реализаций ?
ST>>ответ: только реентерабельность.

GN>Еще и удешевление сопровождения кода. Ужасное количество С кода написано в таком стиле, и для переиспользование приходится передалывать. Код Васи Пупкина можно и не рессматривать, взять старндатную библиотеку С — фукнции вроде gmtime сейчас стали не юзабельны. gmtime_r, или gmtime_s есть не везде. Что далеть то с такими хорошими решениями? Делают даже такие костыли как по отдельному процессу вместо каждого потока


GN>И это еще простая ситуация, когда о проблеме с нереентерабельностью функций заранее известно, а бывает что о таких статиках выясняют после длительного дебага, когда ошибка трудновоспроизводима


ты не то удалил/оставил для ответа
а то потом выясняется, что "из всех искусств для нас важнейшим является кино"(c)
если смотреть мой мессадж целиком, то:

сразу скажу, что мы говорим, конечно, про "pure c".
и тут скорее проще поставить вопрос иначе: какие плюсы у других реализаций ?
ответ: только реентерабельность.

т.е. если нет многопоточных вызовов, то static — это хорошее решение.
реентерабельное решение в чистом си сразу влечет дополнительные сложности реализации и использования.
потому многие чисто сишные функции именно так и реализованы — через static.
как-то так.

Re[10]: Передать массив из функции
От: gear nuke  
Дата: 05.07.10 05:40
Оценка:
Здравствуйте, s.ts, Вы писали:

ST>ты не то удалил/оставил для ответа


Я удалил несущественное. Если сейчас "нет многопоточных вызовов", то завтра они появятся, и решение окажется негодным — поэтому поддержка кода и увеличивается в цене.
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.