Jak zwrócić tablicę z funkcji?

0

Próbuję zwrócić tablicę w funkcji i użyć jej elementu. W Pythonie coś takiego zadziała, w c++ nie działa.

uint32_t funkcja(uint32_t k, uint32_t x)
{
    uint32_t s = k | 1;
    uint32_t w = 0;
    uint32_t wynik[3];

    for (int i = 0; i < 32; i++)
    {
        k += x;
        x = x * k;
        x ^= (w += s);
    }

    wynik[0] = k;
    wynik[1] = x;
    wynik[2] = w;

    return wynik;
}


int main()
{
    uint32_t k_init = 1; 
    uint32_t x_init = 12345;

    uint32_t k = funkcja(k_init, x_init)[0];

    return 0;
}

Dostaję błąd:

error: invalid conversion from ‘uint32_t*’ {aka ‘unsigned int*’} to ‘uint32_t’ {aka ‘unsigned int’}
-fpermissive]

oraz

error: invalid types ‘uint32_t {aka unsigned int}[int]’ for array subscript

O co chodzi?

3

Zadeklarowany typ zwracany przez funkcję to uint32_t czyli 1 zmienna a nie tablica. W C++ nie da się tak zwrócić tablicy, najlepiej użyj vector.

0

Ok, na elektrodzie wyczytałem, że się da:

https://www.elektroda.pl/rtvforum/topic1083584.html

2
struct kxw { uint32_t k,x,w; } foo()
{
  return kxw { 1,2,3 };
}
3
Tomasz_D napisał(a):

Próbuję zwrócić tablicę w funkcji i użyć jej elementu. W Pythonie coś takiego zadziała, w c++ nie działa.

Po pierwsze, to nie jest C++, a jedziesz prawie niezmienione C.
Mam niedobrą wiaodmosć: C z cała pewnością nie jest takim językiem, że da się cokolwiek postąpić bez dokumentacji.
Język cały stoi na udefined behaviour, czy zamiataniu błędów pod dywan.

Zakładając że po czasie prób i błędów być pokonał błąd kompilacji, prawie na pewno byś wszedł na subtelny błąd wykonania, np zwróciłbyś śmieci

Tomasz_D napisał(a):

Ok, na elektrodzie wyczytałem, że się da:

Elektroda a C/C++ to jest "uczył Marcin Marcina"
To w 95% elektronicy, którzy bardzo chcieli programować, natomiast mają zaświadczenie od lekarza, że nie mogą czytać.

_13th_Dragon napisał(a):
struct kxw { uint32_t k,x,w; } foo()
{
  return kxw { 1,2,3 };
}

Najbardziej prawidłowe podejście w nowoczesnym C, zwrócić strukturę.
W prawdziwym C++ to inna rozmowa.

0

Zacznijmy od tego, że zwracanie dużej porcji danych takich jak tablica przez funkcję jest złym pomysłem, dlatego że wszystko co jest zwracane przez funkcję przechodzi przez stos.

Co prawda w dzisiejszych komputerach można mieć ogromny stos i przepychać przez niego co się chce, jednak jest to bardzo zła praktyka.

W Twoim przypadku tablica jest mała i nie ma powodów do obaw, że coś będzie działać "nieoptymalnie", ale warto mieć dobre nawyki.

Tablice w C czy C++ deklaruje się zazwyczaj na zewnątrz funkcji i przekazuje do funkcji wskaźnik do tablicy na której funkcja ma pracować.

void funkcja(uint32_t * p_wynik[3], uint32_t k, uint32_t x)
{
    uint32_t s = k | 1;
    uint32_t w = 0;
    
    for (int i = 0; i < 32; i++)
    {
        k += x;
        x = x * k;
        x ^= (w += s);
    }

    p_wynik[0] = k;
    p_wynik[1] = x;
    p_wynik[2] = w;

}


int main()
{
    uint32_t k_init = 1; 
    uint32_t x_init = 12345;
    uint32_t wynik[3];

    funkcja(&wynik, k_init, x_init)[0]; // przekazujemy do funkcji adres tablicy wynik i parametry

    return 0;
}

Jakbym coś pokręcił to tutaj jest dobry, działający przykład:

https://stackoverflow.com/a/11829889/1215291

0

Napisałem coś takiego:


struct kxw { uint32_t k,x,w; }

uint32_t funkcja(uint32_t k, uint32_t x)
{
    uint32_t s = k | 1;
    uint32_t w = 0;

    for (int i = 0; i < 32; i++)
    {
        k += x;
        x = x * k;
        x ^= (w += s);
    }

    return kxw { k,x,w };
}

int main()
{
    uint32_t k_init = 1; 
    uint32_t x_init = 12345;

    uint32_t k = //jak to wywołać?
    
    return 0;
}

To pewnie nie ma prawa działać, bo tam pewnie trzeba jakoś przypisać elementy tej struktury do zmiennych, nie wiem. Przykłady w Internecie nie sięgają tak daleko, tj. ponad: zdefiniuj strukturę, wywołaj, wypisz.

1

@Tomasz_D: Możesz też tupla użyć:

auto t = std::make_tuple(1,2,3);
4

Mamy 2023 trzeba korzystać z C++11:

std::array<uint32_t, 3> funkcja(uint32_t k, uint32_t x)
{
    uint32_t s = k | 1;
    uint32_t w = 0;
    std::array<uint32_t, 3> wynik;

    for (int i = 0; i < 32; i++)
    {
        k += x;
        x = x * k;
        x ^= (w += s);
    }

    wynik[0] = k;
    wynik[1] = x;
    wynik[2] = w;

    return wynik;
}

std::array opakowuje C-array, tak że jest wygodniejsze w użyciu (da się zwrócić przez wartość).

Jedna zamiast tablic może lepiej zastosować rozwiązanie od Dragona?

0
MarekR22 napisał(a):

Mamy 2023 trzeba korzystać z C++11:

std::array<uint32_t, 3> funkcja(uint32_t k, uint32_t x)
{
    uint32_t s = k | 1;
    uint32_t w = 0;
    std::array<uint32_t, 3> wynik;

    for (int i = 0; i < 32; i++)
    {
        k += x;
        x = x * k;
        x ^= (w += s);
    }

    wynik[0] = k;
    wynik[1] = x;
    wynik[2] = w;

    return wynik;
}

std::array opakowuje C-array, tak że jest wygodniejsze w użyciu (da się zwrócić przez wartość).

Jedna zamiast tablic może lepiej zastosować rozwiązanie od Dragona?

To mi działa. Rozwiązania od Dragona nie umiem użyć w moim przykładzie. Wszystko co wiem o strukturach z internetowych poradników, to jak zdefiniować strukturę, wywołać i wypisać.

1 użytkowników online, w tym zalogowanych: 0, gości: 1