5

We know that C++ allows initialization of C-style arrays with zeros:

int a[5] = {0};
// or
int a[5] = {};

The same works for std::array

std::array a<int, 5> = {};

However, this won't work:

int a[5] = {33}; // in memory( 33, 0, 0, 0, 0 )
std::array<int, 5> = {33}; // in memory( 33, 0, 0, 0, 0 )

Is there any way to initialize the whole array with a non-zero value without using vector or algorhtm?

Maybe constexpr could help? What would be the best solution?

P.S.:

GCC offers this syntax

int a[5] = {[0 ... 4] = 33};

but I am not sure if it is valid for other compilers.

paceholder
  • 1,064
  • 1
  • 10
  • 21
  • 1
    Maybe you need to tighten the requirements because `int a[5] = {33, 33, 33, 33, 33};` – juanchopanza Apr 23 '16 at 12:28
  • Vaguely related: http://stackoverflow.com/q/14797810/560648 – Lightness Races in Orbit Apr 23 '16 at 12:30
  • 2
    Well, Googling your exact title gives: 'About 1,470,000 results'. Maybe there is something in there that may be of use. – Martin James Apr 23 '16 at 12:31
  • 1
    If you're writing C++ then this is not a "C" array. Please remove the tag for whichever language you're _not_ using. – Lightness Races in Orbit Apr 23 '16 at 12:31
  • @LightnessRacesinOrbit "C array" is a way of referring to the sort of array in OP's code , to disambiguate from "C++ array" (i.e. std::vector or std::array) – M.M Apr 23 '16 at 12:32
  • 1
    Pretty much the same question [How to initialize an array in C](http://stackoverflow.com/q/201101/2549281) – Dabo Apr 23 '16 at 12:32
  • 1
    @M.M: It is properly called "an array", without the confusing and misleading qualifier. – Lightness Races in Orbit Apr 23 '16 at 12:32
  • 1
    @LightnessRacesinOrbit on the other hand, *array* is ambiguous with *array* in the `std` namespace. – eerorika Apr 23 '16 at 12:34
  • 3
    @LightnessRacesinOrbit Personally I prefer such a qualifier, it makes discussion clearer IMO. – M.M Apr 23 '16 at 12:35
  • @user2079303: No because you should not be `using namespace std`. There are arrays, and there are `std::array`s. – Lightness Races in Orbit Apr 23 '16 at 12:35
  • @M.M: Yet, if you read the sole answer and the comments underneath it, you'll see that this terminology has caused 100% confusion as to which language is actually being used. "Clearer"? Doesn't look like it! – Lightness Races in Orbit Apr 23 '16 at 12:35
  • The confusion was because OP dual tagged. – M.M Apr 23 '16 at 12:36
  • @M.M: Part of it, yes. Literally writing "C array" made it look like the language being used was C. Hard to miss really – Lightness Races in Orbit Apr 23 '16 at 12:36
  • Unlinked duplicate: that is a C question, but this is a C++ question – M.M Apr 23 '16 at 12:39
  • 3
    @LightnessRacesinOrbit people, even programmers, rarely speak nor type namespaces in English. It is very common to discuss about vector and map and set, even though in C++, such things only exists in the `std` namespace. People discuss about arrays too, and depending on context, they may refer to either form of array or even a vector which is also an array of objects. Therefore there is a need for a way to disambiguate the term. – eerorika Apr 23 '16 at 12:41
  • @user2079303: Yes, but not by adding _more_ ambiguity. – Lightness Races in Orbit Apr 23 '16 at 12:42
  • 4
    Changed from C to C-style – paceholder Apr 23 '16 at 12:43
  • @M.M. The answers are correct for C++; some explicitly mention C++. Now we have to reproduce all the answers here? Great. You get started on that; I'll go for a pint and be back later :) – Lightness Races in Orbit Apr 23 '16 at 12:43
  • @paceholder: Thanks, much better – Lightness Races in Orbit Apr 23 '16 at 12:43
  • There may be solutions which work in C++ but not C , and that thread doesn't cover such solutions. You can mention that thread as providing some assistance but IMO it does not count as "exact duplicate" – M.M Apr 23 '16 at 12:45
  • What is your target here exactly, performance or conciseness of code? Because under the cover it's going to involve a loop however you write it (the `={}` thing for locals gets normally translated to a `memset`), so you aren't going to get significantly better performance than with `std::fill`. – Matteo Italia Apr 23 '16 at 12:48
  • @user2079303 I would suggest *native array* because it is native to the language rather than implemented in a library. Strictly speaking it is `a C++ array` and I prefer not to encourage people to think of `C++` as two different languages. But the term `array` is always going to be a generic term relating to a concept and people naturally use context to disambigue what's intended. The term `C++ array` could mean the Standard Library version or a version from some other library. Its still ambiguous. – Galik Apr 23 '16 at 12:49
  • @Galik I agree, *native array* is good. As are *plain array* and *raw array*. You've expressed my point perhaps more clearly. Just *array* would be ambiguous with the different variations, but even more importantly with the concept. Given the context of C++, *C array* is almost unambiguously a shortening of *C-style array*, but the unfortunate inclusion of unrelated language tag `C` made it ambiguous. – eerorika Apr 23 '16 at 12:56
  • I expect you could use template metaprogramming to achieve this initialisation. Something similar to http://stackoverflow.com/questions/19019252/c11-create-0-to-n-constexpr-array-in-c – paddy Apr 23 '16 at 12:58
  • @user2079303 Although I do use the term "C-style" I am trying to start avoiding that too ;o) If you think about it both `std::vector` and `std::array` are "c-style" arrays (one static and one dynamic) but they happen to be managed by class constructs. I have been known to use the generic term *array* to refer to both of them. I don't think there is a problem being a little ambiguous when context will quickly tell everyone what's being referred to. I think the larger problem is promoting the idea that `C++` is not a complete language in its own right. – Galik Apr 23 '16 at 13:08
  • Your gcc syntax is incorrect - it needs spaces around the dots and it is "..." not ".." e.g this works: int x[5] = {[0 ... 4] = 33}; – Goblinhack Dec 01 '21 at 11:13

2 Answers2

6

What do you have against <algorithm>? I think this is pretty clean:

int a[5];                                  // not initialized here yet
std::fill(std::begin(a), std::end(a), 33); // everything initialized to 33
Barry
  • 286,269
  • 29
  • 621
  • 977
  • Nothing personal, it was more a theoretical question. We have a certain syntax which works for zeros, is there anything similar which might work for non-zeros. – paceholder Apr 23 '16 at 21:31
3

I have some code around to achieve compile-time initialization of an std::array using template meta-programming (of course).

namespace impl {

    template <class SeqTy, size_t N, SeqTy FillVal, SeqTy... Seq>
    struct make_fill {
        using type = typename make_fill<SeqTy, N-1, FillVal, FillVal, Seq...>::type;
    };

    template <class SeqTy, SeqTy FillVal, SeqTy... Seq>
    struct make_fill<SeqTy, 0, FillVal, Seq...> {
        using type = std::integer_sequence<SeqTy, Seq...>;
    };

    template <class T>
    struct make_array;

    template <class SeqTy, SeqTy... Seq>
    struct make_array<std::integer_sequence<SeqTy, Seq...>> {
        static constexpr std::array<SeqTy, sizeof...(Seq)> value() { 
            return std::array<SeqTy, sizeof...(Seq)>{ {Seq...} };
        }
    };

} // end impl namespace

template <class SeqTy, size_t N, SeqTy FillVal = 0ul>
constexpr std::array<SeqTy, N> fill() {
    return impl::make_array<typename impl::make_fill<SeqTy, N, FillVal>::type>::value();
};

which you can use as follows:

std::array<size_t, N> ones = fill<size_t,N,1ul>();

I think you can easily adapt it if you don't want to use std::array

simpel01
  • 1,792
  • 12
  • 13
  • I must admit that my question was valid for std::array as well; the same initialization rules are applied there. Your answer is pretty much what I was looking for. – paceholder Apr 23 '16 at 21:48