-4
#include <iostream>
#include <array>
#include <cstring>

using namespace std;

int main ()
{
  array<int,5> A ;
  memset(A,0,sizeof A);
  for(int i=0;i < 5;i++){
        cout<<A[i]<<" ";
}

   return 0;
}

When I run the program, compilation error occured.

But memset works well when I use int A[5] instead of array<int,5> A. Why memset is not working with container array as either way is used to define fixed size array?

cryptomanic
  • 5,986
  • 3
  • 18
  • 30

3 Answers3

4

Pay close attention to the declaration of memset:

void * memset ( void * ptr, int value, size_t num );

Notice that the first argument must be a pointer.

Raw arrays are special things in c++. You cannot pass them as a parameter to a function as such, but if a function takes a pointer as a parameter, then an array of appropriate type will decay to a pointer to first element. That is why you can pass a raw array to a function that expects a pointer.

std::array is not a raw array, but a regular class. Class instances do not decay to a pointer. That is why you cannot pass an instance of std::array as a parameter of memset.

As explained in comments already, you shouldn't use memset to initialize std::array anyway.

Community
  • 1
  • 1
eerorika
  • 232,697
  • 12
  • 197
  • 326
1

std::memset should work fine with std::array. If you look at the declaratoin of std::memset you will see it takes a pointer to the array, that is why your code does not work.

void* memset( void* dest, int ch, std::size_t count );

This should work:

memset(A.data(), 0, A.size() * sizeof(A[0]);

Like others have pointed out, in your example it is better to initialize the array

array<int, 5> A = {};
rozina
  • 4,120
  • 27
  • 49
  • 1
    Your use of `memset` here has a problem. `A` is an array of `int` and `memset` fills __bytes__ of memory. Passing `A.size()` is the number of _elements_, you'll need to scale it by the _sizeof an element_. Better yet, just use the `std::array::fill` member function... – Blastfurnace Jun 29 '15 at 13:11
  • @Blastfurnace Thanks, was not paying attention. Will fix the code. I know that memset() is not good to use in this case, but the question is not asking if it is good, it is asking why it is not working. – rozina Jun 29 '15 at 13:41
  • 1
    Your fix isn't quite right, `A.size()` is the number of elements so you want to __multiply__ it by the size of an element to get the number of bytes to fill. – Blastfurnace Jun 29 '15 at 14:03
  • @Blastfurnace Ups again :) Thanks! – rozina Jun 29 '15 at 14:56
-1

memset(A,0,sizeof A); is incorrect. This is an anti-pattern. The way to set an object to all-bits-zero (for objects that permit this operation) is:

memset(&obj, 0, sizeof obj);

or if we have a pointer to object:

memset(ptr, 0, sizeof *ptr);

Your form happens to "work" for C-style arrays because A decays to a pointer but sizeof A doesn't decay. But for non-arrays you will get a size mismatch (or an outright error). Sticking to one of the two canonical forms avoids size mismatches.


std::array is not required to be implemented as a C-style array, so using memset on it is not appropriate. If you are creating the array you can simply write:

array<int,5> A = {};

If you need to reset the array later then you can use:

A.fill(0);
M.M
  • 138,810
  • 21
  • 208
  • 365
  • Is std::array a "POD" or standard-layout and if so, should it then be "memsettable"? See http://stackoverflow.com/questions/3674247/is-stdarrayt-s-guaranteed-to-be-pod-if-t-is-pod – André Jun 29 '15 at 11:43
  • 2
    **−1** "std::array is not required to be implemented as a C-style array" is incorrect. – Cheers and hth. - Alf Jun 29 '15 at 11:44
  • Additional info: C++14 §23.3.2.1/1 "The elements of an `array` are stored contiguously, meaning that if `a` is an `array` then it obeys the identity `&a[n] == &a[0] + n` for all `0 <= n < N`" – Cheers and hth. - Alf Jun 29 '15 at 11:49
  • in the fourth line size of *ptr should be repaced by size of ptr – cryptomanic Jun 29 '15 at 11:50
  • @DeepakY4-YrBTechComputerS no it shouldn't – M.M Jun 29 '15 at 12:28
  • @Cheersandhth.-Alf your quote doesn't imply that `std::array` wraps a C-style array. In fact, see the next page after your quote where it says **exposition only** with note "The member variable `elems` is shown for exposition only, to emphasize that array is a class aggregate". `array` might be implemented as some other aggregate besides a C-style array. – M.M Jun 29 '15 at 12:33
  • @Cheersandhth.-Alf another thing is that `std::array` is well-defined, however C-style arrays may not have length 0 , therefore `std::array` cannot wrap a C-style array. – M.M Jun 29 '15 at 12:35
  • Regarding your last line of code, you might prefer to use the `std::array::fill` member function. – Blastfurnace Jun 29 '15 at 13:07
  • @Matt: the standard quote defines the `array` storage as a C style array. there is no implication, it's directly a C style array. size 0 is a special case, yes, and it does not imply anything (as you think). – Cheers and hth. - Alf Jun 29 '15 at 13:30
  • @Cheersandhth.-Alf It doesn't directly define it as a C-style array. It only says it must have the same semantics. Other implementations are possible. It goes out of its way to say *aggregate* instead of *array*. – M.M Jun 29 '15 at 13:36
  • @MattMcNabb: that's argumentative. and pretty meaningless. and attempted telepathic as to intent. – Cheers and hth. - Alf Jun 29 '15 at 13:37