NOVINKA - Online rekvalifikační kurz Python programátor. Oblíbená a studenty ověřená rekvalifikace - nyní i online.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.
Avatar
Belzebub
Člen
Avatar
Belzebub:12.12.2023 18:28

Ahoj,
vytvářím software pro ESP32. Bádám nad způsobem, jakým způsobem nejlépe předávat řetězce, a to s ohledem
na rychlost, paměťovou náročnost, přehlednost programu... Mám tyto tři příklady:
1.

char buffer[256] = "";

char* testString() {
  snprintf(buffer, sizeof(buffer), "ABC%sGHI", "DEF");
  return buffer;
}

int main() {
    printf("testString() = %s\n", testString());
    return 0;
}

2.

char *testString() {
  char *str = (char *)malloc(256);
  snprintf(str, 256, "ABC%sGHI", "DEF");
  return str;
}

int main() {
    char *test_string = testString();
    printf("testString() = %s\n", test_string);
    free(test_string);
    return 0;
}

3.

typedef struct {
  char str[256];
} string_t;

string_t testString() {
  string_t s;
  snprintf(s.str, sizeof(s.str), "ABC%sGHI", "DEF");
  return s;
}

int main() {
    printf("testString() = %s\n", testString().str);
    return 0;
}
  1. způsob se mi líbí asi nejvíc, nyní používám jen 2 buffery pro mnoho funkcí, ale musím myslet na to, abych náhodou nepoužil buffer znova ve vnořené funkci. Nejlepší varianta je asi, aby každá funkce měla svůj buffer, to bude zabírat více paměti...
  2. způsob je asi nejsprávnější, ale kód je delší a je třeba myslet na free
  3. způsob se mi také líbí, ale přenos řetězce prý probíhá kopírováním, což je asi pomalejší, také si nejsem jist, kdy se proměnná s uvolní z paměti... je příklad vůbec správný?
  4. možná je nějaká jiná lepší možnost?

Díky za pomoc zkušenějších, jelikož stále tápu v tom, jak se používá paměť v C, tak nevím, co je lepší..

Editováno 12.12.2023 18:29
 
Odpovědět
12.12.2023 18:28
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Belzebub
DarkCoder:13.12.2023 1:18

Správně by ten dotaz měl znít: Jak vracet řetězec z funkce. To co požaduješ je velmi komplexní a nelze to popsat na pár řádků. Je to proto, že těch možností, jak toho dosáhnout, je mnoho a navyšuje se to ještě podle situace. Nebudu zde rozebírat základní pojmy jako řetězec, ukazatele, typy alokací, globální a lokální proměnné, apod., ale nastíním na jednoduchém příkladu několik možností jak pracovat s řetězcem "vráceným" z funkce. Vráceným v uvozovkách proto že se nevrací celý řetězec ale ukazatel na pole tvořící řetězec.

Následný program ukazuje 4 způsoby jak "vrátit" řetězec z funkce. V tomto případě řetězec "Hello".

#include <stdio.h>
#include <string.h>

#define BUFFER_LIMIT 10

char* return_Hello(char* buffer, char** p_buffer);

int main(void) {
        char buffer[BUFFER_LIMIT];
        char* p_buffer = NULL;

        // 1. prime pouziti
        puts(return_Hello(buffer, NULL));

        // 2. neprime pouziti
        (void)return_Hello(buffer, NULL);
        puts(buffer);

        // 3. modifikace navratove hodnoty
        p_buffer = return_Hello(buffer, NULL);
        puts(p_buffer);

        // 4. modifikace argumentu
        (void)return_Hello(buffer, &p_buffer);
        puts(p_buffer);

        return 0;
}

char* return_Hello(char* buffer, char** p_buffer) {
        const char* hello = "Hello";
        size_t length = strnlen(hello, BUFFER_LIMIT - 1);

        strncpy(buffer, hello, length);
        buffer[length] = '\0';

        if (p_buffer) *p_buffer = buffer;

        return buffer;
}

1. přímé použití
Operace s řetězcem je přes vrácený ukazatel z funkce který má jednorázový charakter.

2. nepřímé použití
Operace s řetězcem je přes ukazatel na začátek řetězce. Funkce slouží pouze k modifikaci řetězce.

3. modifikace návratové hodnoty
Operace s řetězcem je přes vrácený ukazatel z funkce který má permanentní charakter. Toto je nejčastější varianta.

4. modifikace argumentu
Operace s řetězcem je přes ukazatel předaný funkci jako argument.

Principy pro dynamickou alokaci se nijak zásadně neliší. Operace s řetězci se provádí výhradně pomocí ukazatelů.

Znovu, téma je příliš široké na to, abych dokázal detailně zodpovědět všechny tvé dotazy. Pokud Tě cokoli z toho více zajímá dopodrobna, ptej se, ale výrazně specifikuj oblast.

Nahoru Odpovědět
13.12.2023 1:18
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 2 zpráv z 2.