-1

I want to initialize a 2D array with -1 as all the value. I used memset() for this.

#include <bits/stdc++.h>
using namespace std;

int dp[100][100];
memset(dp, -1, sizeof(dp));

int dynamicProgramming(some parameters)
{
    //I want to use dp[][] array here
}

int main() {
    cout<<dp[99][99];
    return 0;
}

But I am getting an error as

prog.cpp:5:7: error: expected constructor, destructor, or type conversion before ‘(’ token
 memset(dp, -1, sizeof(dp));

Can you tell me the correct way to do it?

Sachin Kumar
  • 366
  • 1
  • 6
  • 20
  • 3
    You can't have an executable statement like `memset(...)` outside a function! Put that line *inside* `main`. Also see: [Why should I not #include ?](https://stackoverflow.com/q/31816095/10871073). – Adrian Mole Jun 10 '20 at 12:01
  • 3
    Please see your C++ textbook. All C++ code must appear in some function or class method, instead of the global initialization section, like that. You could move the memset call inside `main()`, perhaps. Still, there are several other fundamental issues that are wrong with this approach. – Sam Varshavchik Jun 10 '20 at 12:01
  • I want global initialization – Sachin Kumar Jun 10 '20 at 12:06
  • 1
    You cannot initialize global variables in this manner. C++ does not work this way. You will need to find some other way to solve your problem. – Sam Varshavchik Jun 10 '20 at 12:07
  • 2
    Be aware that memset does bytewise initialisation! As there's no recent machine any more not using 2's complement, you most likely are **lucky** and get desired result that way, as all four bytes of each int look alike. Try with +1 instead, though, and you'll get a pretty different result. (Hint: It's equal to 1 + 256 + 256² + 256³ on typical modern 64-bit and on older 32-bit hardware.) – Aconcagua Jun 10 '20 at 12:08
  • plz see the edited version, I am trying to solve a dynamic programming problem using memoization @SamVarshavchik – Sachin Kumar Jun 10 '20 at 12:16
  • 1
    I don't know what "dynamic programming" means, and, in any case, C++ still doesn't work this way. No matter what you're trying to do you cannot change how C++ works, fundamentally. The only thing that could be done here is to use `std::array` and an initialization function. This would be horribly inefficient, though. See your C++ textbook for more information and description on how to use `std::array`. – Sam Varshavchik Jun 10 '20 at 12:18
  • Just initialize the variable in main. – drescherjm Jun 10 '20 at 12:21
  • Are you looking for https://stackoverflow.com/a/10897934/4645334? Usually I would recommend to avoid compiler specific extension but your code already is compiler specific and it seems ok for you. – Thomas Sablik Jun 10 '20 at 14:28
  • @SamVarshavchik An object at namespace scope can be declared with an initialiser, which can be a function, and we could write one here that would return an array filled with the desired value. That's not necessarily slower, if copy elision occurs, especially from C++17 where guaranteed copy elision should definitely elide such a copy. Right? – underscore_d Jun 10 '20 at 14:31
  • All you have to do, @underscore_d, is to try to figure out how to return an array from a function. Unfortunately, this is not possible in C++. – Sam Varshavchik Jun 10 '20 at 14:43
  • @SamVarshavchik Right, sorry, I meant an `std::array` specifically (or any other real object). I use that pattern of initialising-from-functions extensively into `std::array`s and find it really useful. It sure beats having to 'initialise' separately or use dynamic containers, etc. – underscore_d Jun 10 '20 at 14:43
  • Copy elision is only guaranteed, basically, for prvalues. NRVO is not guaranteed, but it is likely that most modern C++ compilers will elide the copy in that case. In any case, the OP wants to initialize a plain array. – Sam Varshavchik Jun 10 '20 at 14:45
  • @SamVarshavchik [Dynamic programming](https://en.wikipedia.org/wiki/Dynamic_programming) is a Computer Science fundamental, often taught in degree courses and used to solve real-life algorithmic problems. – Asteroids With Wings Jun 10 '20 at 19:23
  • Oh, it's just buzzword bingo, ok. It didn't have that fancy name in my college days, it was simply called "the right way to do things". It's still unclear how that has to do with the subject matter here, though. – Sam Varshavchik Jun 10 '20 at 19:45

6 Answers6

3

There is no way (at least I do not know any) to initialize all the elements of an array with a specific value other than 0.

You can somehow work around in that you call memset in the course of initializing another variable at file scope:

int dp[100][100];
auto x = memset(dp, -1, sizeof(dp));

int main() {
    cout<<dp[99][99];
    return 0;
}

But note: the order of global variable initialization is not guaranteed; the only thing you can rely on is that the memset will have been executed before function main is entered. But then you could do it as first line in main as well.

Note further that you need good luck when you want to initialize an array elements of type int, as a single int comprises more than one byte; memset fills the elements at byte level, not at element type level. For example, memset(dp, -2, sizeof(dp)) will not lead to an array filled with -2 then; and even -1 requires the architecture to be two's complement to work.

Stephan Lechner
  • 34,891
  • 4
  • 35
  • 58
  • Technically not fully correct, as initialisation of x can be deferred – before C++17, though, that might badly fail, as deferring is legal until first ODR-use of x (and dp might have been accessed before). I don't think it's a good idea to show such code to beginners – especially if you don't show how one would do usually... – Aconcagua Jun 10 '20 at 13:40
2

As others have said, you can't call memset in the global scope. The most correct and clear vay is probably going to be something like

#include <iostream>
using namespace std;

const int D1 = 100;
const int D2 = 100;
int dp[D1][D2];

void initializeDp()
{
    for (int i = 0; i < D1; i++) {
        for (int j = 0; j < D2; j++) {
            dp[i][j] = -1;
        }
    }
}

int main() {
    initializeDp();
    cout << dp[D1-1][D2-1];
    return 0;
}

If you count global variables as a good practice, obviously. I personally would use a 2d std::array, so it would contain its size itself

Expurple
  • 877
  • 6
  • 13
1
for (auto& v : dp) {
    std::fill(std::begin(v), std::end(v), -1);
}

Inside function, not global scope.

Amir Kadyrov
  • 1,253
  • 4
  • 9
1

You can't use memset in the global scope. It must be written in main scope.

#include <bits/stdc++.h>
using namespace std;

int dp[100][100];

int main() {
    memset(dp, -1, sizeof(dp));
    cout<<dp[99][99];
    return 0;
}
  • 2
    Correct location for memset – question, though, is 'how to initialise a 2d array?', and memset is not the way to go. You should address that as well. – Aconcagua Jun 10 '20 at 13:46
1

In practice, in this case, it is possible to write an helping templated function, itself based on simple for-range loops.

One advantage is that is will work for other types of 2D arrays.

#include    <iostream>

template <typename T2d, typename T>
void init2d (T2d &arr, T val) {
    for (auto& row: arr) {
        for (auto& i: row) {
            i = val;
        }
    }       
}

int main() {
    const int  n = 5, m = 6;
    int a[n][m];

    init2d (a, -1);
    std::cout << a[n-1][m-1] << "\n";
}

If you want to initialize before main, the simplest way is to rely on STL, e.g. on std::vector or std::array, like this, for a 5x6 matrix:

std::vector<std::vector<int>> b(5, std::vector<int> (6, -1));
Damien
  • 4,809
  • 4
  • 15
  • 20
  • I was about to write an answer with the vector solution mentioned here, though you need to add a space in `>>`, i.e. `std::vector > b(5, std::vector (6, -1));` (The edit queue was full, so I wrote this comment so that people can see why the example would not compile). – Nikolaj Sep 23 '21 at 15:28
  • @Nikolaj In practice, this space is no longer useful in the last versions of the standard (since C++14 if I remember well). – Damien Sep 23 '21 at 15:57
0

It seems like you are looking for a way to init a global array before main like described in Call a function before main? Usually I would recommend to avoid compiler specific extension but your code already is compiler specific and it seems ok for you. This is a gcc extension. It can cause strange errors. Other global objects could be uninitialized. Parts of this code probably causes undefined behavior. Just do it if you want to shoot you in your foot.

#include <bits/stdc++.h>
using namespace std;

void beforeMain (void) __attribute__((constructor));

int dp[100][100];
void beforeMain (void) {
    memset(dp, -1, sizeof(dp));
}

int main() {
    std::cout << dp[0][0] << std::endl;
}
Thomas Sablik
  • 16,127
  • 7
  • 34
  • 62