Inicializace normálního pole s jednou výchozí hodnotou

hlasů
190

C ++ Poznámky: Array Inicializace má pěkný přehled nad inicializaci pole. já mám

int array[100] = {-1};

čekal, že bude plný -1, ale není to jen první hodnota a zbytek je 0 se smíchá s náhodnými hodnotami.

Kód

int array[100] = {0};

funguje v pohodě a nastaví každý prvek na hodnotu 0.

Co jsem zde chybí .. Nelze jeden inicializaci v případě, že hodnota není nula?

2: Je výchozí inicializace (viz výše) rychleji, než je obvyklé procházet celé pole a přiřadit hodnotu, nebo to dělá to samé?

Položena 30/06/2009 v 21:10
zdroj uživatelem
V jiných jazycích...                            


13 odpovědí

hlasů
8

S {} přiřadit prvky jako jsou deklarovány; Zbytek se inicializuje s 0.

Není-li = {}k initalize, jejichž obsah je definován.

Odpovězeno 30/06/2009 v 21:13
zdroj uživatelem

hlasů
291

Pomocí syntaxe, který jste použili,

int array[100] = {-1};

říká „nastavení prvního prvku k -1a zbytek se 0“, protože všechny vynechané prvky jsou nastaveny na 0.

V jazyce C ++, nastavte je všechny -1, můžete použít něco jako std::fill_n(od <algorithm>):

std::fill_n(array, 100, -1);

V přenosném C, budete muset vytvořit vlastní smyčky. Existuje kompilátoru rozšíření nebo se můžete spolehnout na implementaci definovaných chování jako zástupce, pokud je to přijatelné.

Odpovězeno 30/06/2009 v 21:14
zdroj uživatelem

hlasů
8

Stránka, kterou spojené státy

Není-li uvedeno výslovně velikost pole, ale kratší seznam initiliazation je zadán, nespecifikované prvky jsou nastaveny na nulu.

Problém Speed: Případné rozdíly by byly zanedbatelné pro pole této malé. Pokud pracujete s velkými poli a rychlost je mnohem důležitější než velikost, můžete mít const řadu výchozích hodnot (inicializovat při kompilaci) a pak memcpyjim na modifikovatelné pole.

Odpovězeno 30/06/2009 v 21:14
zdroj uživatelem

hlasů
2

1) Při použití inicializátor pro struct nebo pole, jako je to, že jsou blíže neurčené hodnoty jsou v zásadě default postavena. V případě primitivního typu, jako je ints, to znamená, že budou vynulována. Všimněte si, že se to týká rekurzivně: můžete mít řadu structs obsahujících pole a pokud zadáte pouze první pole prvního struct, pak všechno ostatní bude inicializovat nulami a výchozí konstruktérů.

2) kompilátor pravděpodobně přinesou Inicializátor kód, který je přinejmenším stejně dobrý jako byste mohli dělat ručně. I upřednostňují nechat kompilátor dělat inicializace pro mě, pokud je to možné.

Odpovězeno 30/06/2009 v 21:15
zdroj uživatelem

hlasů
29

Stránka, kterou souvisí s již dal odpověď na první část:

Není-li uvedeno výslovně velikost pole, ale kratší seznam initiliazation je zadán, nespecifikované prvky jsou nastaveny na nulu.

Neexistuje žádné vestavěné způsob inicializace celého pole do určité nenulovou hodnotu.

Pokud jde o který je rychlejší, obvykle platí pravidlo: „Metoda, která dává kompilátor největší volnost je pravděpodobně rychleji“.

int array[100] = {0};

jednoduše říká kompilátoru „set těchto 100 celých čísel na nulu“, které kompilátor může libovolně optimalizovat.

for (int i = 0; i < 100; ++i){
  array[i] = 0;
}

je mnohem konkrétnější. Říká kompilátoru vytvořit iterační proměnnou i, že to řekne pořadí , ve kterém by měly být prvky inicializován, a tak dále. Samozřejmě, že překladač je pravděpodobné, že optimalizovat to pryč, ale jde o to, že zde jsou overspecifying problém, nutí kompilátor pracovat těžší se dostat ke stejnému výsledku.

A konečně, pokud chcete nastavit pole na nenulovou hodnotu, měli byste (v jazyce C ++, přinejmenším) pomocí std::fill:

std::fill(array, array+100, 42); // sets every value in the array to 42

Opět platí, že byste mohli udělat to samé s poli, ale to je výstižnější, a dává kompilátor větší svobodu. Jenom tím, že chcete, aby se celé pole naplněno hodnotou 42. Neříkejte nic o tom, v jakém pořadí by mělo být provedeno, nebo cokoliv jiného.

Odpovězeno 30/06/2009 v 21:18
zdroj uživatelem

hlasů
122

K dispozici je rozšíření gcc kompilátor, který umožňuje syntaxi:

int array[100] = { [0 ... 99] = -1 };

Tím by se nastavit všechny prvky -1.

Toto je známé jako „Určená Inicializátory“ Podívejte se zde pro další informace.

Poznámka: toto není realizován pro gcc kompilátor C ++.

Odpovězeno 30/06/2009 v 21:22
zdroj uživatelem

hlasů
1

Pro případ pole jednobajtových prvků, můžete použít memset nastavit všechny prvky na stejnou hodnotu.

Tam je příklad zde .

Odpovězeno 01/07/2009 v 08:31
zdroj uživatelem

hlasů
1

V jazyce C ++ je také možné použít meta programování a variadic šablon. Následující příspěvek ukazuje, jak na to: Programová vytvořit statické matice při kompilaci v jazyce C ++ .

Odpovězeno 13/03/2014 v 14:14
zdroj uživatelem

hlasů
0

V C ++ programovacího jazyka V4, Stroustrup doporučuje použití vektorů nebo valarrays přes vestavěných polí. S valarrary letech, kdy jejich vytvoření, můžete je init na určitou hodnotu, jako je:

valarray <int>seven7s=(7777777,7);

K inicializaci pole 7 členů dlouhá „7777777“.

Jedná se o C ++ způsob, kterým se provádí odpověď pomocí struktury C ++ dat namísto „obyčejné C“ pole.

Přešel jsem k používání valarray jako pokus v mém kódu, aby se pokusili použít C ++ "ismů v. C'isms ....

Odpovězeno 14/05/2014 v 02:21
zdroj uživatelem

hlasů
3

Další způsob, jak inicializaci pole na společnou hodnotu, by bylo skutečně vytvořit seznam prvků v sérii definuje:

#define DUP1( X ) ( X )
#define DUP2( X ) DUP1( X ), ( X )
#define DUP3( X ) DUP2( X ), ( X )
#define DUP4( X ) DUP3( X ), ( X )
#define DUP5( X ) DUP4( X ), ( X )
.
.
#define DUP100( X ) DUP99( X ), ( X )

#define DUPx( X, N ) DUP##N( X )
#define DUP( X, N ) DUPx( X, N )

Inicializaci pole na společnou hodnotu lze snadno provést:

#define LIST_MAX 6
static unsigned char List[ LIST_MAX ]= { DUP( 123, LIST_MAX ) };

Poznámka: DUPx zavedena k tomu, aby makro substituci v parametry DUP

Odpovězeno 23/07/2014 v 09:39
zdroj uživatelem

hlasů
8

C ++ 11 má další možnost (nedokonalé):

std::array<int, 100> a;
a.fill(-1);
Odpovězeno 11/09/2014 v 10:20
zdroj uživatelem

hlasů
2

Pomocí std::array, můžeme to udělat v poměrně jednoduchým způsobem v C ++ 14. To je možné udělat v C ++ pouze 11, ale o něco složitější.

Naše rozhraní je velikost kompilace-time a výchozí hodnota.

template<typename T>
constexpr auto make_array_n(std::integral_constant<std::size_t, 0>, T &&) {
    return std::array<std::decay_t<T>, 0>{};
}

template<std::size_t size, typename T>
constexpr auto make_array_n(std::integral_constant<std::size_t, size>, T && value) {
    return detail::make_array_n_impl<size>(std::forward<T>(value), std::make_index_sequence<size - 1>{});
}


template<std::size_t size, typename T>
constexpr auto make_array_n(T && value) {
    return make_array_n(std::integral_constant<std::size_t, size>{}, std::forward<T>(value));
}

Třetí funkce je hlavně pro pohodlí, takže uživatel nemusí postavit std::integral_constant<std::size_t, size>sami, protože to je docela rozvláčný konstrukce. Skutečná práce se provádí jeden z prvních dvou funkcí.

První přetížení je velice jednoduché: Je konstruuje std::arrayvelikosti 0. Není kopírování nutné, abychom to prostě postavit.

Druhý přetížení je trochu složitější. Předá podél hodnoty, kterou dostal jako zdroj, a to také konstruuje instanci make_index_sequencea právě volá nějakou jinou funkci implementace. Co tato funkce vypadá?

namespace detail {

template<std::size_t size, typename T, std::size_t... indexes>
constexpr auto make_array_n_impl(T && value, std::index_sequence<indexes...>) {
    // Use the comma operator to expand the variadic pack
    // Move the last element in if possible. Order of evaluation is well-defined
    // for aggregate initialization, so there is no risk of copy-after-move
    return std::array<std::decay_t<T>, size>{ (static_cast<void>(indexes), value)..., std::forward<T>(value) };
}

}   // namespace detail

To konstruuje první velikosti - 1 argumenty zkopírováním hodnotu, kterou prošel v Zde jsme využít naše variadic parametrů balení indexy stejně jako něco rozšířit.. Existují velikost - 1 záznamů v tomto balení (tak jak je uvedeno ve výstavbě make_index_sequence), a mají hodnoty 0, 1, 2, 3, ..., velikost - 2. Nicméně, my se nestarají o hodnotách ( takže jsme vrci ztrátu, umlčet žádná varování kompilátoru). Parametr datadisk rozšiřuje naši kód něčemu takovému (za předpokladu, velikost == 4):

return std::array<std::decay_t<T>, 4>{ (static_cast<void>(0), value), (static_cast<void>(1), value), (static_cast<void>(2), value), std::forward<T>(value) };

Používáme ty závorky, aby variadic datadisk ...rozšiřuje to, co chceme, a zároveň zajistit, abychom se pomocí operátoru čárka. Bez závorek, bylo by to vypadat míjíme spoustu argumentů v našem inicializaci pole, ale ve skutečnosti jsme vyhodnocení indexu, casting ji ruší, ignoroval tu prázdnotu výsledek, a pak se vracet hodnotu, která je zkopírována do pole ,

Konečný argument ta nazýváme std::forwarddál, je menší optimalizace. Pokud se někdo prochází dočasné std :: string a říká, že „dělat řadu 5 z nich“, bychom chtěli mít 4 kopie a 1 tah, místo 5 kopií. Tyto std::forwardzajistí, že to uděláme.

Plné kód, včetně záhlaví a některé jednotkové testy:

#include <array>
#include <type_traits>
#include <utility>

namespace detail {

template<std::size_t size, typename T, std::size_t... indexes>
constexpr auto make_array_n_impl(T && value, std::index_sequence<indexes...>) {
    // Use the comma operator to expand the variadic pack
    // Move the last element in if possible. Order of evaluation is well-defined
    // for aggregate initialization, so there is no risk of copy-after-move
    return std::array<std::decay_t<T>, size>{ (static_cast<void>(indexes), value)..., std::forward<T>(value) };
}

}   // namespace detail

template<typename T>
constexpr auto make_array_n(std::integral_constant<std::size_t, 0>, T &&) {
    return std::array<std::decay_t<T>, 0>{};
}

template<std::size_t size, typename T>
constexpr auto make_array_n(std::integral_constant<std::size_t, size>, T && value) {
    return detail::make_array_n_impl<size>(std::forward<T>(value), std::make_index_sequence<size - 1>{});
}

template<std::size_t size, typename T>
constexpr auto make_array_n(T && value) {
    return make_array_n(std::integral_constant<std::size_t, size>{}, std::forward<T>(value));
}



struct non_copyable {
    constexpr non_copyable() = default;
    constexpr non_copyable(non_copyable const &) = delete;
    constexpr non_copyable(non_copyable &&) = default;
};

int main() {
    constexpr auto array_n = make_array_n<6>(5);
    static_assert(std::is_same<std::decay_t<decltype(array_n)>::value_type, int>::value, "Incorrect type from make_array_n.");
    static_assert(array_n.size() == 6, "Incorrect size from make_array_n.");
    static_assert(array_n[3] == 5, "Incorrect values from make_array_n.");

    constexpr auto array_non_copyable = make_array_n<1>(non_copyable{});
    static_assert(array_non_copyable.size() == 1, "Incorrect array size of 1 for move-only types.");

    constexpr auto array_empty = make_array_n<0>(2);
    static_assert(array_empty.empty(), "Incorrect array size for empty array.");

    constexpr auto array_non_copyable_empty = make_array_n<0>(non_copyable{});
    static_assert(array_non_copyable_empty.empty(), "Incorrect array size for empty array of move-only.");
}
Odpovězeno 03/12/2015 v 04:53
zdroj uživatelem

hlasů
-5

By měla být standardní funkce, ale z nějakého důvodu to není zahrnuto ve standardním C ani C ++ ...

#include <stdio.h>

 __asm__
 (
"    .global _arr;      "
"    .section .data;    "
"_arr: .fill 100, 1, 2; "
 );

extern char arr[];

int main() 
{
    int i;

    for(i = 0; i < 100; ++i) {
        printf("arr[%u] = %u.\n", i, arr[i]);
    }
}

V Fortran můžete udělat:

program main
    implicit none

    byte a(100)
    data a /100*2/
    integer i

    do i = 0, 100
        print *, a(i)
    end do
end

ale to nemá nepodepsané čísla ...

Proč nelze C / C ++ právě jeho realizaci. Je to opravdu tak těžké? Je to tak hloupé psát to ručně, aby se dosáhlo stejného výsledku ...

#include <stdio.h>
#include <stdint.h>

/* did I count it correctly? I'm not quite sure. */
uint8_t arr = {
    2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
    2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
    2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
    2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
    2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
    2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
    2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
    2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
    2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
    2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
};    

int main() 
{
    int i;

    for(i = 0; i < 100; ++i) {
        printf("arr[%u] = %u.\n", i, arr[i]);
    }
}

Co když to byl řada 1,000,00 bytů? Potřeboval bych napsat skript psát to pro mě, nebo se uchylují k rozsekává s montáží / etc. To je nesmysl.

Je to naprosto přenosný, neexistuje žádný důvod pro to, aby se v jazyce.

Jen to hack v takto:

#include <stdio.h>
#include <stdint.h>

/* a byte array of 100 twos declared at compile time. */
uint8_t twos[] = {100:2};

int main()
{
    uint_fast32_t i;
    for (i = 0; i < 100; ++i) {
        printf("twos[%u] = %u.\n", i, twos[i]);
    }

    return 0;
}

Jeden způsob, jak proniknout do probíhá přes předzpracování ... (kód níže nezahrnuje případy hrany, ale je psán rychle ukázat, co by se dalo dělat.)

#!/usr/bin/perl
use warnings;
use strict;

open my $inf, "<main.c";
open my $ouf, ">out.c";

my @lines = <$inf>;

foreach my $line (@lines) {
    if ($line =~ m/({(\d+):(\d+)})/) {
        printf ("$1, $2, $3");        
        my $lnew = "{" . "$3, "x($2 - 1) . $3 . "}";
        $line =~ s/{(\d+:\d+)}/$lnew/;
        printf $ouf $line;
    } else {
        printf $ouf $line;
    }
}

close($ouf);
close($inf);
Odpovězeno 03/04/2016 v 11:27
zdroj uživatelem

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more