Tablica znaków jako parametr funkcji (const pointer)

0

Szukam sposobu na przekazanie do funkcji tablicy uint32_t, ale wstukanej "z ręki".

Coś takiego:

void Test(const uint32_t* Tablica)
{

}

Sęk w tym, że taka funkcja nie przyjmie takiego parametru:

Test({0xAABBCCDD, 0xBBCCAAEE})

Natomiast coś takiego już pójdzie, ale w sposób pośredni, a to mi nie wystarczy:

const uint32_t Array[] = {0xAABBCCDD, 0xBBCCAAEE};
Test(Array);

Póki co udało mi się wykombinować tyle, żeby jako parametr podawać const stringa w formie znaków unicode. Niestety nie ma znaków dla pełnego zakresu 32 bitowego inta, więc zamiast tego muszę się posługiwać char'em, który na szczęście ma odpowiednie znaki unicode w pełnym zakresie 0-255:

//To nie działa:

void Test(const char32_t* Tablica)
{
  
}

Test("\UAABBCCDD\UBBCCAAEE"); //Error, nie ma takich znaków unicode

//Ale to tak:

void Test(const char* Tablica)
{
  
}

Test("\xAA\xBB\xCC\xDD\xBB\xCC\xAA\xEE"); //OK

Wiem, że mógłbym to zrobić na 10 innych sposobów, np. podając kolejne wartości w formie initializer_list, ale wtedy całość nie będzie miała postaci ciągłej tablicy bajtów (na tym mi zależy) i będzie wymagała wstępnej obróbki do takiej postaci.

Jakieś pomysły?

2
#include <iostream>
#include <iomanip>
using namespace std;

void Test(const char32_t* Tablica)
{
	for(char32_t ch;(ch=*(Tablica++))!=0;)
	{
		cout<<"0x"<<setw(8)<<hex<<((uint32_t)ch)<<endl;
	}
}

int main()
{
    const char32_t Array[] = {0xAABBCCDD, 0xBBCCAAEE,0};
	Test(Array);
	Test(U"\UAABBCCDD\UBBCCAAEE"); // dla standardu C++11 działa ale nie każdy kompilator to akceptuje.
	return 0;
}

https://learn.microsoft.com/en-us/cpp/cpp/string-and-character-literals-cpp?view=msvc-170

0

Jednia linia kodu:

Test({0xAABBCCDD, 0xBBEECCDD});

Dwie linie kodu:

const uint32_t Array[] = {0xAABBCCDD, 0xBBEECCDD};
Test(Array);

Właśnie tego dotyczy moje zapytanie, czy istnieje możliwość wklepania tablicy bezpośrednio jako parametr funkcji, bez tworzenia pośredniej zmiennej. Tak trudno to zrozumieć? Nie ważne do czego mi to potrzebne, chcę tylko wiedzieć, czy jest to możliwe inaczej, niż poprzez unicode i tablicę 8 bitową (char), tyle.

3

Nie do końca rozumiem pytanie.
Jak masz inicjator:

Test({0xAABBCCDD, 0xBBEECCDD});

To użyj inicjatora.

void Test(const std::initializer_list<uint32_t> array)

Pointner do danych będziesz miał w array.begin(). Bajty będą w little-endian (na x86).
Potrzebujesz jakiejś automatycznej konwersji z inicjatora na pointner?

2

Dajesz rzutowanie inline lub
jak napisał @malencki robisz initializer i po krzyku.

#include <iostream>
#include <iomanip>
using namespace std;

void Test(const char32_t *Tablica)
{
	for(char32_t ch;(ch=*(Tablica++))!=0;)
	{
		cout<<"0x"<<setw(8)<<hex<<((uint32_t)ch)<<endl;
	}
}

void test(const std::initializer_list<uint32_t> Tablica) { Test((const char32_t *)Tablica.begin()); }

int main()
{
	const char32_t Array[] = {0xAABBCCDD, 0xBBCCAAEE,0};
	Test(Array);
 	Test((const char32_t[]){0xAABBCCDD, 0xBBCCAAEE,0}); // rzutowanie
	test({0xAABBCCDD, 0xBBCCAAEE,0}); // initializer
	return 0;
}
1

@Crow:
Jeszcze mi przyszło do głowy, że możesz w sumie użyć tego featura z c++20:

void test(const uint32_t (&& item)[]){
    std::cout << std::hex << item[0] << "\n" << item[1] << "\n";
}

int main(){
    test({0xAABBCCDD, 0xBBCCAAEE});
}

Zawsze trochę mniej pisania.
Ale nie masz wielkości, więc wtedy albo wiesz ile jest elementów lub też stosujesz jakieś dziwaczne znaczniki jak pisał @_13th_Dragon .

2

Ale nie masz wielkości, więc wtedy albo wiesz ile jest elementów lub też stosujesz jakieś dziwaczne znaczniki jak pisał @_13th_Dragon .

Ja bym to napisał tak:

template<typename T, size_t N>
void test(const T (&& item)[N]){
    for(const auto & el: item) cout << el << "\n";
}
0

Jako paskalowiec nawrócony na C++ chciałem sie zapytać co trzeba przestawić w sposobie myślenia aby widzieć rozwiązania które bazują na "template" ?

Co trzeba przeczytać aby wszystko zrozumieć ?

template<typename T, size_t N>
void test(const T (&& item)[N]){
    for(const auto & el: item) cout << el << "\n";
}
test({0xAABBCCDD, 0xBBCCAAEE,0xBBCCAAEE});

rozwijane jest do

void test(const size_t (&& item)[3] ){
    for(auto el: item) std::cout << el << "\n";
}

ale dlaczego && a nie & ?

3
malencki napisał(a):

@Crow:
Jeszcze mi przyszło do głowy, że możesz w sumie użyć tego featura z c++20:

void test(const uint32_t (&& item)[]){
    std::cout << std::hex << item[0] << "\n" << item[1] << "\n";
}

int main(){
    test({0xAABBCCDD, 0xBBCCAAEE});
}

Zawsze trochę mniej pisania.
Ale nie masz wielkości, więc wtedy albo wiesz ile jest elementów lub też stosujesz jakieś dziwaczne znaczniki jak pisał @_13th_Dragon .

Jak już C++20 to std::span i od ręki masz załatwione, C-array, std::array, std::vector.
Niestety nie pokrywa std::initializer_list :(, więc konieczny jest dodatkowy overload.
https://godbolt.org/z/bhzYcYxTq

void test(std::span<const uint32_t> items)
{
    for (auto x : items) {
        std::cout << x << ", ";
    }
    std::cout << "\n";
}
void test(std::initializer_list<uint32_t> items)
{
    test(std::span{ items.begin(), items.size() });
}

Swoja drogą w żadnym projekcie jaki pracowałem nie przeszło by:

test({0xAABBCCDD, 0xBBCCAAEE});

z powodu magic numbers.

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