leonel shovo
leonel shovo

Reputation: 51

Initializing values by memsets

I have used an array as dt[100]; then,i have initialize the values like memset(dt,63,sizeof(dt)); then i have seen the value assigned in those array like 4557430888798830399.can i have the explanation?

#include <bits/stdc++.h>
#define ll long long int
using namespace std;
ll dt[100];
int main()
{

 memset(dt,63,sizeof(dt));
 cout<<dt[0]<<endl;

}

Upvotes: 0

Views: 961

Answers (4)

David Haim
David Haim

Reputation: 26476

well, answers here are almost right.
the most flexible, correct solution is to use std::fill with std::begin + std::end

std::fill(std::begin(dt),std::end(dt),63);
  1. you should use std::fill instead of memset, because std::fill is aware of objects and will call the correct assignment operation. memset knows only what a byte is (C vs C++).
  2. memset fills bytes, std::fill fills any variable with any size
  3. std::fill will call memset or memmove anyway if the variable size equals a byte size (yes, the standard library is not that stupid as we might think it is..)
  4. std::begin + std::end "know" the size of a C array, so no erroneous stuff like arr , arr + 100 which breaks the moment the array size is changed
  5. std::begin + std::end work with C arrays and any C++ container which supplies begin() and end() methods (vector , deque , list etc). so without putting any effort, the code is general (the sizeof trick will not work for std::vector, for example).

as for why does the long long has such weird value, is because memset fills every byte and not every long long.
so, assuming each long long is 8 bytes, memory wise, the long long after the memset looks like

byte
  |
  V
[63][63][63][63][63][63][63][63]
^                               ^
|        long long              | 

and in binary :

0011111100111111001111110011111100111111001111110011111100111111 
//63 == 00111111, 8 bytes of each

which is :

4557430888798830399

(I deliberately did not go into endianess details in order not to complicate the subject too much)

Upvotes: 10

Jens
Jens

Reputation: 9406

As others have already pointed out, the memset copies 63 to each byte of the array. That is why your numbers are not what you expect. You should also try to avoid memset and memcpy in C++ and only use it when you are sure that the objects being copied are PODs or standard-layout types. Copying general C++ objects can be very problematic, and memsetting objects is a recipe for disaster.

An alternative to std::fill, which is fully ok, is to not use plain C arrays at all. Instead, use either std::vector<long long> or std::array<long long, N>.

To create a vector of 10 elements with value 63:

std::vector<long long> v(10, 63);

To create a statically allocated array of 10 elements with value 63

std::array<long, long, 10> a;
a.fill(63);

PS: try not to use #define for typedefs or constants or inline functions. C++ has type-safe replacements for most C constructs.

Upvotes: 2

Smeeheey
Smeeheey

Reputation: 10316

As per above answers, byte-level filling is the reason you get what you get. As an alternative to above suggestions, you could use this:

std::fill(dt, dt+100, 63);

The advantage here is that this is more likely to be optimized and thus quicker than manually looping over the memory (e.g. it could use SIMD vector instructions on x86_64 architectures)

Upvotes: 4

barak manos
barak manos

Reputation: 30126

As mentioned in a comment by @Michael Burr, function memset sets the value of each char in the given block of memory, while each cell in your array is long long.

Alternative solutions:

for (size_t i=0; i<sizeof(dt)/sizeof(*dt); i++)
    dt[i] = 63;

for (auto& n : dt)
    n = 63;

Upvotes: 1

Related Questions