#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?
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.
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 = {};
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);
Related
I'm struggling to pass a C99 static 3D array of variable length to a function. I know this has been asked here on SO before, but I tried every solution I found so far, none of them worked. I have a following code:
int N;
int foo( ? ){
// do stuff
}
int main(){
cin >> N;
int arr[N][N][N];
foo(arr);
return 0;
}
The question is what to put instead of '?'. Among other things I tried creating a pointer to this 3D array and passing the pointer according to the answer here but that also would compile.
C++ does not have variable-style arrays. What you can do is cast the address of the array to a pointer, and pass the dimensions, or even cast to a pointer to an array of the same size but different shape, then dereference that pointer.
One C++ technique you can use to sugar this, if you are selecting between a finite number of possible shapes, is to declare a template< size_t L, size_t M, size_t N> int foo( int arr[L][M][N]). Another would be a multidimensional array class that wraps your array and its dimensions. You can then construct an object, which aliases rather than copies the array, that you can index as arr(i, j, k).
I am learning c pointer and I follow c4learn as tutorial. In pointer to array of string section, which has following code:
char *arr[4] = {"C","C++","Java","VBA"};
char *(*ptr)[4] = &arr;
I didn't get what is
*(*ptr)[4]
? Wasn't it possible to use it like
**ptr
instead?
Update1:
Currently I am in the next section, function pointer and I saw again similar code:
void *(*ptr)();
char *(*ptr)[4]
is a pointer to a length 4 array of pointers to char (char*). Since arr is a length 4 array of char*, ptr can be made to point to arr by assigning it the address of arr, &arr.
void *(*ptr)();
Is a pointer to a parameterless function returning void*. For example
void* fun(); // function
void *(*ptr)(); // function pointer
p = fun; // function pointer points to function
C syntax can be quite confusing, so it may be easier to illustrate this with some examples. Note that whitespaces between T and ; make no difference.
T name[N]; // size N array of T
T * name[N]; // size N array of pointer to T
T (*name)[N]; // pointer to size N array of T
T ** name[N]; // size N array of pointer to pointer to T
T *(*name)[N]; // pointer to size N array of pointer to T
char *ar[4];
Declares ar as an array of four pointers to chars.
To declare a pointer, you take the declaration of something it can point to, and replace the variable name with (*some_other_name).
So char *(*ptr)[4]; declares ptr as a pointer to an array of four pointers to chars. Normally you can drop the brackets, but in this case, char **ptr[4]; would declare ptr as an array of four pointers to pointers to chars which is not what we want.
Similarly for a function pointer. void *fn() declares a function. void *(*ptr)() declares a pointer that could point to fn. void **ptr() would declare a function with a different return type.
Wasn't it possible to use it like **ptr instead?
Yes, assuming you mean like ptr2 below:
const char* arr[4] = {"C","C++","Java","VBA"};
const char* (*ptr)[4] = &arr;
const char** ptr2 = arr;
There is a difference though... with ptr the type still encodes the array length, so you can pass ptr but not ptr2 to functions like the one below:
template <size_t N>
void f(const char* (&arr)[N]) { ...can use N in implementation... }
Currently I am in the next section, function pointer and I saw again similar code: void *(*ptr)();
That creates a pointer to a function - taking no arguments - returning a void* (i.e. the address of an unspecified type of data, or nullptr).
char *(*ptr)[4] is an array pointer to an array of pointers.
With less obfuscated syntax: if you have a plain array int arr[4]; then you can have an array pointer to such an array by declaring int (*arr_ptr)[4].
So there are arrays, regular pointers and array pointers. Things get confusing because when you use the array name by itself, arr, it decays into a regular pointer to the first element. Similarly, if you have a regular pointer and let it point at the array, ptr = arr; it actually just points at the first element of the array.
Array pointers on the other hand, points at the "whole array". If you take sizeof(*arr_ptr) from the example above, you would get 4*sizeof(int), 4*4=16 bytes on a 32-bit machine.
It should be noted that an array pointer a mildly useful thing to have. If you are a beginner, you don't really need to waste your time trying to understand what this is. Array pointers are mainly there for language consistency reasons. The only real practical use for array pointers is pointer arithmetic on arrays-of-arrays, and dynamic allocation of multi-dimensional arrays.
I wrote this code for the following problem. My compiler is givin me the following error- [Error] declaration of 'a' as array of references. What is the problem?
void repfunc(int& a[],int size){
for(int i=size-1;i>=0;--i){
if(a[i]==0){
a[i]=1;
return;
}
for(int j=i-1;j>=0;--ji){
if(a[i]==a[j]&&a[i]!=9){
++a[i];
a[i]%=10;
return;
}
else if(a[i]==a[j]&&a[i]==9){
a[j-1]++;
a[j-1]%=10;
FOR(k, 1,size-j){
a[k]=k;
}
return;
}
}
}
}
As the error says, you can't have an array of references. It looks like you're actually trying to pass an array by reference. You can (sort of) do that by changing it to take a pointer to the start of the array:
void repfunc(int a[], int size) // equivalent to "int * a"
Since arrays are convertible to pointers, this will do the right thing if the argument is an array
int a[4] = {1,2,3,4};
repfunc(a, sizeof a / sizeof a[0]);
Alternatively, you could accept a reference to an array of the correct size:
template <size_t size>
repfunc(int (&a)[size])
allowing the size to be deduced automatically
int a[4] = {1,2,3,4};
repfunc(a);
but note that this will only work if a is actually an array; not, for example an pointer to a dynamically allocated array.
C++ Standard 8.3.2/4 clearly says that:
There shall be no references to references, no arrays of references, and no pointers to references
Actually a reference must always refer to something - there is no such thing as a null reference. This is why there can be no arrays of references, as there is no way to default instantiate references inside an array to a meaningful value.
-Source is Here.
And also By origin array is accessed via pointer arithmatic. So if we want to support array of reference we have to support pointer to reference, as per standard which is not possible.
These are reason array of reference is not possible. Which is what you were doing. And as Mike Seymour mentioned :
void repfunc(int a[], int size) is perfectly ok for your case.
Apparently, we can pass complex class instances to functions, but why can't we pass arrays to functions?
The origin is historical. The problem is that the rule "arrays decay into pointers, when passed to a function" is simple.
Copying arrays would be kind of complicated and not very clear, since the behavior would change for different parameters and different function declarations.
Note that you can still do an indirect pass by value:
struct A { int arr[2]; };
void func(struct A);
Here's another perspective: There isn't a single type "array" in C. Rather, T[N] is a a different type for every N. So T[1], T[2], etc., are all different types.
In C there's no function overloading, and so the only sensible thing you could have allowed would be a function that takes (or returns) a single type of array:
void foo(int a[3]); // hypothetical
Presumably, that was just considered far less useful than the actual decision to make all arrays decay into a pointer to the first element and require the user to communicate the size by other means. After all, the above could be rewritten as:
void foo(int * a)
{
static const unsigned int N = 3;
/* ... */
}
So there's no loss of expressive power, but a huge gain in generality.
Note that this isn't any different in C++, but template-driven code generation allows you to write a templated function foo(T (&a)[N]), where N is deduced for you -- but this just means that you can create a whole family of distinct, different functions, one for each value of N.
As an extreme case, imagine that you would need two functions print6(const char[6]) and print12(const char[12]) to say print6("Hello") and print12("Hello World") if you didn't want to decay arrays to pointers, or otherwise you'd have to add an explicit conversion, print_p((const char*)"Hello World").
Answering a very old question, as Question is market with C++ just adding for completion purposes, we can use std::array and pass arrays to functions by value or by reference which gives protection against accessing out of bound indexes:
below is sample:
#include <iostream>
#include <array>
//pass array by reference
template<size_t N>
void fill_array(std::array<int, N>& arr){
for(int idx = 0; idx < arr.size(); ++idx)
arr[idx] = idx*idx;
}
//pass array by value
template<size_t N>
void print_array(std::array<int, N> arr){
for(int idx = 0; idx < arr.size(); ++idx)
std::cout << arr[idx] << std::endl;
}
int main()
{
std::array<int, 5> arr;
fill_array(arr);
print_array(arr);
//use different size
std::array<int, 10> arr2;
fill_array(arr2);
print_array(arr2);
}
The reason you can't pass an array by value is because there is no specific way to track an array's size such that the function invocation logic would know how much memory to allocate and what to copy. You can pass a class instance because classes have constructors. Arrays do not.
Summery:
Passing the Address of the array's first element &a = a = &(a[0])
New Pointer (new pointer, new address, 4 bytes, in the memory)
Points to the same memory location, in different type.
Example 1:
void by_value(bool* arr) // pointer_value passed by value
{
arr[1] = true;
arr = NULL; // temporary pointer that points to original array
}
int main()
{
bool a[3] = {};
cout << a[1] << endl; // 0
by_value(a);
cout << a[1] << endl; // 1 !!!
}
Addresses:
[main]
a = 0046FB18 // **Original**
&a = 0046FB18 // **Original**
[func]
arr = 0046FB18 // **Original**
&arr = 0046FA44 // TempPTR
[func]
arr = NULL
&arr = 0046FA44 // TempPTR
Example 2:
void by_value(bool* arr)
{
cout << &arr << arr; // &arr != arr
}
int main()
{
bool a[3] = {};
cout << &a << a; // &a == a == &a[0]
by_value(arr);
}
Addresses
Prints:
[main] 0046FB18 = 0046FB18
[func] 0046FA44 != 0046FB18
Please Note:
&(required-lvalue): lvalue -to-> rvalue
Array Decay: new pointer (temporary) points to (by value) array address
readmore:
Rvalue
Array Decay
It was done that way in order to preserve syntactical and semantic compatibility with B language, in which arrays were implemented as physical pointers.
A direct answer to this question is given in Dennis Ritchie's "The Development of the C Language", see the "Critique" section. It says
For example, the empty square brackets in the function declaration
int f(a) int a[]; { ... }
are a living fossil, a remnant of NB's way of declaring a pointer; a is, in this special case only, interpreted in C as a pointer. The notation survived in part for the sake of compatibility, in part under the rationalization that it would allow programmers to communicate to their readers an intent to pass f a pointer generated from an array, rather than a reference to a single integer. Unfortunately, it serves as much to confuse the learner as to alert the reader.
This should be taken in the context of the previous part of the article, especially "Embryonic C", which explains how introduction of struct types in C resulted in rejection of B- and BCPL-style approach to implementing arrays (i.e. as ordinary pointers). C switched to non-pointer array implementation, keeping that legacy B-style semantics in function parameter lists only.
So, the current variant of array parameter behavior is a result of a compromise: one the one hand, we had to have copyable arrays in structs, on the other hand, we wanted to preserve semantic compatibility with functions written in B, where arrays are always passed "by pointer".
The equivalent of that would be to first make a copy of the array and then pass it to the function (which can be highly inefficient for large arrays).
Other than that I would say it's for historical reasons, i.e. one could not pass arrays by value in C.
My guess is that the reasoning behind NOT introducing passing arrays by value in C++ was that objects were thought to be moderately sized compared to arrays.
As pointed out by delnan, when using std::vector you can actually pass array-like objects to functions by value.
You are passing by value: the value of the pointer to the array. Remember that using square bracket notation in C is simply shorthand for de-referencing a pointer. ptr[2] means *(ptr+2).
Dropping the brackets gets you a pointer to the array, which can be passed by value to a function:
int x[2] = {1, 2};
int result;
result = DoSomething(x);
See the list of types in the ANSI C spec. Arrays are not primitive types, but constructed from a combination of pointers and operators. (It won't let me put another link, but the construction is described under "Array type derivation".)
actually, a pointer to the array is passed by value, using that pointer inside the called function will give you the feeling that the array is passed by reference which is wrong. try changing the value in the array pointer to point to another array in your function and you will find that the original array was not affected which means that the array is not passed by reference.
Why does n not equal to 8 in the following function?
void foo(char cvalue[8])
{
int n = sizeof (cvalue);
}
But n does equal to 8 in this version of the function:
void bar()
{
char cvalue[8];
int n = sizeof (cvalue);
}
Because you can't pass entire arrays as function parameters in C. You're actually passing a pointer to it; the brackets are syntactic sugar. There are no guarantees the array you're pointing to has size 8, since you could pass this function any character pointer you want.
// These all do the same thing
void foo(char cvalue[8])
void foo(char cvalue[])
void foo(char *cvalue)
C and C++ arrays are not first class objects; you cannot pass arrays to functions, they always decay to pointers.
You can, however, pass pointers and references to arrays. This prevents the array bounds from decaying. So this is legal:
template<typename T, size_t N>
void foo(const T(&arr)[N])
{
int n = sizeof(arr);
}
In the first example, cvalue as passed parameter is in really just a pointer to a character array and when you take the sizeof() of it, you get the size of the pointer. In the second case, where you've declared it as a local variable, you get the size of the the entire array.
The size of the parameter on 32-bit systems will be 4 and on 64-bit systems compiled with -m64 will be 8. This is because arrays are passed as pointers in functions. The pointer is merely a memory address.