LINUX.ORG.RU

string[] to char * char[]

 ,


0

4

Приветствую.

День тупняка сегодня…

Надобно передать мне в сишную функцию чужой либы статичный массив char * const *, но как бы вот так хитрожопо его создать вроде

char * services[] = {(char*)"1", (char*)"22", (char*)"333"};

но что бы можно было собрать его из std::string по типу

std::string services[] = {"1"+var1, var2+"22", "333" + var3 + "333"};

штоб не создавать левых переменных, динамических массивов, циклов переприсвоения и все освободилось атхаматом выйдя из области видимости )

★★★

Последнее исправление: wolverin (всего исправлений: 2)

создай строки отдельно и заполни services через присваивание. По другому никак. Даже если ты массив из строк фиксированной длины сделаешь, потом надо будет делать второй массив из указателей

mittorn ★★★★★
()

все освободилось атхаматом выйдя из области видимости

если данных немного и ты контролируешь их размер, то вполне:

alloca(x)

но аккуратно и умеючи

MKuznetsov ★★★★★
()

штоб не создавать левых переменных, динамических массивов,

std::string это динамический массив char (за исключением оптимизации для коротких строк)

zx_gamer ★★★
()

Интересная задача, придумал такое.

#include <initializer_list>
#include <cstring>
#include <cstdio>
#include <functional>

inline __attribute__((always_inline)) void strarray (
    std::initializer_list<std::initializer_list<const char*>> strarr, 
    auto f
) {
    size_t fullsize = sizeof(const char *) * strarr.size();
    for (auto subarr : strarr) {
        for (auto str : subarr) fullsize += strlen(str);
        fullsize += 1;
    }
    char buff[fullsize];
    char **pe = (char**)buff;
    char *pi = buff + sizeof(const char *) * strarr.size();
    for (auto subarr : strarr) {
        *pe++ = pi;
        for (auto str : subarr) {
            size_t len = strlen(str);
            memcpy(pi, str, len + 1);
            pi += len;
        }
        pi++;
    }
    return f((char**)buff);
}

void c_function(const char * const* arr, int n) {
    for (int i = 0; i < n; ++i) puts(arr[i]);
}

int main() {
    strarray({
        {"Hello", "World", "!"},
        {"Concat", "String"}
    }, [](char **arr) { c_function(arr, 2); });
}
Да, тут memcpy, заполнение массива, но без копирования совсем не обойтись, строки по другому не совместить.

Не нашел способа сделать alloc из вызывающей функции, поэтому пошел обратным путем, и передаю массив во внутреннюю функцию, лямбду.

MOPKOBKA ★★★★
()
Последнее исправление: MOPKOBKA (всего исправлений: 1)

c_str() освободится вместе со своим std::string

TheAnonymous ★★★★★
()
Ответ на: комментарий от MOPKOBKA

buff[fullsize];

выделение памяти на стёке.

return f((char**)buff);

Ссылка на эту память.

Вас ничего не смущает?

Да, тут memcpy, заполнение массива, но без копирования совсем не обойтись, строки по другому не совместить.

ИМХО тут х3 использованной памяти из-за преобразования char* в это ваше std::initializer_list<std::initializer_list<const char*>> strarr

Ygor ★★★★★
()
Последнее исправление: Ygor (всего исправлений: 1)
Ответ на: комментарий от Ygor

Вас ничего не смущает?

А если без загадок? Все работает без ворнингов. return лишний, его нужно убрать, пропустил.

ИМХО тут х3 использованной памяти из-за преобразования char* в это ваше std::initializer_list<std::initializer_list<const char*>> strarr

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

MOPKOBKA ★★★★
()
Последнее исправление: MOPKOBKA (всего исправлений: 2)
Ответ на: комментарий от MOPKOBKA

А если без загадок? Все работает без ворнингов.

Все норм, ты передаёшь этот адрес, и функция в котором этот адрес живёт существует до возврата из той куда этот адрес передали.

Ygor ★★★★★
()
Ответ на: комментарий от MOPKOBKA

Все работает без ворнингов.

) все не проверял ибо перевариваю еще, но на такие вещи у меня всегда пишет

char buff[fullsize];

warning: ISO C++ forbids variable length array ‘buff’
wolverin ★★★
() автор топика

наваял вопщим такое

struct stTopics
{
    const std::vector<std::string> vTopics;

    stTopics(const std::vector<std::string> vec)
    : vTopics(vec)
    {}

    size_t size(void) const
    {
        return vTopics.size();
    }

    char * const * c_arr(void)
    {
        std::vector<const char *> cArr(size());

        for (auto & v : vTopics) cArr.push_back(v.c_str());

        return (char * const *)cArr.data();
    }
};

Объявляю как stTopics topics({"1"+var1, var2+"22", "333" + var3 + "333"}) - не проверял еще, но компилируется )

wolverin ★★★
() автор топика
Ответ на: комментарий от wolverin

VLA появился позже в стандарте, вместо него можно использовать

#include <alloca.h>
char *buff = alloca(fullsize);

MOPKOBKA ★★★★
()
Последнее исправление: MOPKOBKA (всего исправлений: 1)
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.