This question already has answers here:
How come an array's address is equal to its value in C?
(6 answers)
Closed 7 years ago.
I have a struct defined in my program.
struct A{
int arr[10];
}
Lets say I have a pointer to it.
A * a = new A;
I can zero it in two ways:
memset(&a->arr,0,sizeof(A));
memset(a->arr,0,sizeof(A));
both work and look the same!
which one is more correct?
which one is more correct?
I'd argue neither. The easiest way would be to value initialize the allocated object:
A * a = new A();
Of course, this assumes that you actually have a good reason to new this object.
Since you are using C++ I would take advantage of C++11 features and use:
#include <iostream>
#include <cmath>
using namespace std;
struct A{
int arr[10]{}; // initializes array with all 0's
};
int main() {
A * a = new A;
for (auto e : a->arr) // ranged based for loop to show all of the 0's
cout << e << "\n";
return 0;
}
You can see it running with this Live Example
While the type of each expression is different, the actual result, the pointer you pass to memset, will be equal in both cases.
Personally I would probably use std::fill instead of memset in a C++ program:
std::fill(std::begin(a->arr), std::end(a->arr), 0);
Also note that if you have more members in the structure, sizeof(A) will be different from sizeof(a->arr) (or sizeof(A::arr)).
you can define a default construct function
struct A{
int arr[10];
A():arr(){}
};
This is the correct way for just the array
memset(a->arr,0,sizeof(a->arr))
Picked out the arr member just in case there are other structure members that do not need to be touched. Makes no difference in your example the following will do likewise
memset(a->arr,0,sizeof(A));
Related
This question already has answers here:
Why aren't variable-length arrays part of the C++ standard?
(10 answers)
Why a const size is needed in an array?
(1 answer)
Closed 4 months ago.
I want to convert a float vector to a float array in C++ 20. I searched online and found this solution:
#include <iostream>
#include <algorithm>
#include <vector>
int main()
{
std::vector<int> input({ 1, 2, 3, 4, 5 });
int arr[input.size()];
std::copy(input.begin(), input.end(), arr);
for (int i: arr) {
std::cout << i << ' ';
}
return 0;
}
But when I try to implement it, the compiler gives me an error saying that what's inside the brackets in the array declaration must be a constant expression.
Since when is this the case? I swear I've declared arrays in a similar manner in C++ before and it worked. And if you look online you'll see that everyone does this too, the example I posted seems to be the standard solution to my problem. So why does it give me an error?
Since when is this the case?
Since always. In standard C++, you cannot allocate a block of memory on the stack if you don't know its size at compile time.
Some compilers allow it as an extension. It's also standard in C99, and these arrays are then known as variable-length array.
A lot of what you see online is non standard. Just because someone does something that works for them doesn't mean it will work for you. In this case, it can certainly work for you if you don't care about writing cross-platform, standard compliant code. But if you want to write standard compliant code, you have basically two choices: make an array with a large enough size, known at compile time, and only use part of it, or don't use an array.
To address your comment:
Because a third party function (OpenGL) requires an array as an argument.
No function requires an array as argument. It can require a raw block of memory, but then you also need to give it the size of that block. You can easily do that with a std::vector, using the methods data() and size().
The only way I know of to require an array as argument is through some template magic:
template<std::size_t N>
void print_size(int (&array)[N]) {
std::cout << N;
}
Demo
Even then, you can apparently pass it a vector if you specify the size (might be undefined behavior):
std::vector<int> v = {1, 2, 3};
print_size<3>(reinterpret_cast<int(&)[3]>(*v.data()));
This question already has answers here:
When a function has a specific-size array parameter, why is it replaced with a pointer?
(3 answers)
Closed 9 years ago.
Why in C++ sizeof(array) behave in different way for bool array then for arrays containing other types of data ?
Edition :
I'm asking because
sizeof(boolarray)/sizeof(boolarray[0])
don't give size of boolarray.
but this simple code prints :
4
1
////////////////////////////
#include<iostream>
using namespace std;
void printBoolArray(bool* boolarray){
cout<<sizeof(boolarray)<<"\n";
cout<<sizeof(boolarray[0]);
}
int main(){
bool boolarray[10]={false};
printBoolArray(boolarray);
}
know I understand sizeof in function which gives the size of object which makes reference, this is my 9 day with c++, sorry for stupid question, it's so obvious now
It doesn't act differently. What makes you think it does? Are you making incorrect assumptions about the size of a bool?
As has been alluded to in the comments, if you are passing an array to a function and attempting to calculate its size there, that doesn't work. You can't pass arrays to (or return them from) functions. For example:
void foo(int array[10])
{
auto size = sizeof(array);
// size == sizeof(int*), you didn't pass an array
}
#include <cstddef>
#include <iostream>
template<std::size_t n>
void printBoolArray(bool (&boolarray)[n]){
std::cout<<sizeof(boolarray)<<"\n";
std::cout<<sizeof(boolarray[0]);
}
int main(){
bool boolarray[10]={false};
printBoolArray(boolarray);
}
The above works.
sizeof(bool*) is the size of the pointer, not the array it points to.
Above, I carefully maintained the type of the boolarray. As it happens, this technique also extracts the size into the compile-time constant n.
This doesn't scale well, because when you pass arrays to functions, they rapidly decay to pointers. This is one of the reasons why std::array or std::vector can be advised -- they have fewer quirks than C style arrays.
As others have explained, arrays degenerate to pointers when passed to a function.
However, there is one work around; you can use templates.
template<typename T, size_t N>
size_t length(T (&)[N]) {
return N;
}
This question already has answers here:
Why can one specify the size of an array in a function parameter?
(3 answers)
Closed 3 years ago.
This feels like a really stupid thing to ask, but I had someone taking a programming class ask me for some help on an assignment and I see this in their code (no comments on the Hungarian notation please):
void read_dictionary( string ar_dictionary[25], int & dictionary_size ) {...
Which, as mainly a C# programmer (I learned about C and C++ in college) I didn't even know you could do. I was always told, and have read since that you're supposed to have
void read_dictionary( string ar_dictionary[], int ar_dictionary_size, int & dictionary_size ) {...
I'm told that the professor gave them this and that it works, so what does declaring a fixed size array like that even mean? C++ has no native way of knowing the size of an array being passed to it (even if I think that might've been changed in the newest spec)
In a one dimensional array It has no significance and is ignored by the compiler. In a two or more dimensional array It can be useful and is used by the function as a way to determine the row length of the matrix(or multi dimensional array). for example :
int 2dArr(int arr[][10]){
return arr[1][2];
}
this function would know the address of arr[1][2] according to the specified length, and also the compiler should not accept different sizes of arrays for this function -
int arr[30][30];
2dArr(arr);
is not allowed and would be a compiler error(g++) :
error: cannot convert int (*)[30] to int (*)[10]
The 25 in the parameter declaration is ignored by the compiler. It's the same as if you'd written string ar_dictionary[]. This is because a parameter declaration of array type is implicitly adjusted to a pointer to the element's type.
So the following three function declarations are equivalent:
void read_dictionary(string ar_dictionary[25], int& dictionary_size)
void read_dictionary(string ar_dictionary[], int& dictionary_size)
void read_dictionary(string *ar_dictionary, int& dictionary_size)
Even in the case of the first function, with the size of the array explicitly declared, sizeof(ar_dictionary) will return the same value as sizeof(void*).
See this sample on Codepad:
#include <string>
#include <iostream>
using namespace std;
void read_dictionary(string ar_dictionary[25], int& dictionary_size)
{
cout << sizeof(ar_dictionary) << endl;
cout << sizeof(void*) << endl;
}
int main()
{
string test[25];
int dictionary_size = 25;
read_dictionary(test, dictionary_size);
return 0;
}
Output (the exact value is, of course, implementation-dependent; this is purely for example purposes):
4
4
I always though that passing fixed size C++ arrays was a "half baked" feature of C++. For example, ignored size matching or only being able to specify the first index size, etc... Until recently I learn this idiom:
template<size_t N1, size_t N2> // enable_if magic can be added as well
function(double(&m)[N1][N2]){
... do something with array m...knowing its size!
}
Reference: Can someone explain this template code that gives me the size of an array?
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Returning local data from functions in C and C++ via pointer
I need to create a function with no arguments that returns an array
I get the error: "warning: function returns address of local variable"
my code has been simplified for ease of reading
int * getNums()
{
int nums[8];
nums = {1,2,3,4,5,6,7,8};
return nums;
}
I am led understand that when the function ends the pointer is lost, but will the array still be sent? If not, what is a good way to return this integer array with no arguments in the function call?
Appreciate the help in advance!
Cheers
No, the array will not be "sent". You need to do one of these:
create the array dynamically using new
create the array statically
pass the array into the function as a pointer
use std::vector
In most cases, the last is the preferred solution.
Pretend you don't know what C-arrays are and join the world of modern C++:
#include <array>
std::array<int, 8> getNums()
{
std::array<int, 8> ret = {{ 1, 2, 3, 4, 5, 6, 7, 8 }};
return ret;
}
If your compiler is too old to provide a std:: or std::tr1:: implementation of array<>, consider using boost::array<> instead. Or, consider using std::vector<> either way.
I am led understand that when the function ends the pointer is lost, but will the array still be sent?
The behavior is undefined.
what is a good way to return this integer array with no arguments in the function call?
int nums[8];
num is local variable which resides on stack. You cannot return the reference of a local variable. Instead alloc nums with operator new and remember to delete[] it.
int* getNums()
{
int *nums = new int[8] ;
// .....
return nums ;
}
// You should deallocate the resources nums acquired through delete[] later,
// else memory leak prevails.
Whenever a function exits all the local variables created within that function get trashed.
You are creating an array local to the function and then returning a pointer to the array. The returned pointer will point to an memory location which is already reclaimed by the OS. So it wont work for you.
Instead of Arrays, You should use vectors, since it is C++
You can't return a simple array in C++. Try
int *getNums()
{
int *nums = new int[8];
...
return nums;
}
Now nums is a pointer to a heap array which will live on after getNums returns.
int* getNums()
{
static int nums[8];
nums = {1,2,3,4,5,6,7,8};
return nums;
}
It should propabally work now :)
Your array is a regular stack-based local variable. That means that it disappears when you return from the function and returning a pointer to it does not work. You have to make the array live longer, which can be done by turning it into a static variable or allocating it on the heap:
int *getArray {
static int foo[] = {…};
return foo;
}
int *getArray {
int foo[] = calloc(numberOfItems, sizeof(int));
foo = …;
return foo;
}
Both solutions have implications that you should understand before you use one. Namely, the static allocation (first option) is mainly a curiosity nowaydays, since it creates a sort of a global variable and causes more problems than it solves. The heap-allocated array is quite common, but it’s more customary to pass the pointer to fill using an argument to make the interface more explicit. In every case the caller is responsible for freeing the allocated memory later.
And, as others note, there are even better solutions specific to C++, if you don’t insist on using a plain C array.
I have a struc like this:
struct process {int PID;int myMemory[];};
however, when I try to use it
process p;
int memory[2];
p.myMemory = memory;
I get an criptic error from eclipse saying int[0] is not compatible with int[2];
what am i doing wrong?
Thanks!
Don't use static arrays, malloc, or even new if you're using C++. Use std::vector which will ensure correct memory management.
#include <vector>
struct Process {
int pid;
std::vector<int> myMemory;
};
Process p;
p.reserve(2); // allocates enough space on the heap to store 2 ints
p.myMemory.push_back( 4815 ); // add an index-zero element of 4815
p.myMemory.push_back( 162342 ); // add an index-one element of 162342
I might also suggest creating a constructor so that pid does not initially have an undefined value:
struct Process {
Process() : pid(-1), myMemory() {
}
int pid;
std::vector<int> myMemory;
};
I think you should declare myMemory as an int* then malloc() when you know the size of it. After this it can be used like a normal array. Int[0] seems to mean "array with no dimension specified".
EXAMPLE:
int *a; // suppose you'd like to have an array with user specified length
// get dimension (int d)
a = (int *) malloc(d * sizeof(int));
// now you can forget a is a pointer:
a[0] = 5;
a[2] = 1;
free((void *) a); // don't forget this!
All these answers about vector or whatever are confused :) using a dynamically allocated pointer opens up a memory management problem, using vector opens up a performance problem as well as making the data type a non-POD and also preventing memcpy() working.
The right answer is to use
Array<int,2>
where Array is a template the C++ committee didn't bother to put in C++99 but which is in C++0x (although I'm not sure of the name). This is an inline (no memory management or performance issues) first class array which is a wrapper around a C array. I guess Boost has something already.
In C++, array definition is almost equal to pointer constants, meaning that their address cannot be changed, while the values which they point to can be changed. That said, you cannot copy elements of an array into another by the assignment operator. You have to go through the arrays and copy the elements one by one and check for the boundary conditions yourself.
The syntax ...
struct process {int PID;int myMemory[];};
... is not valid C++, but it may be accepted by some compilers as a language extension. In particular, as I recall g++ accepts it. It's in support for the C "struct hack", which is unnecessary in C++.
In C++, if you want a variable length array in a struct, use std::vector or some other array-like class, like
#include <vector>
struct Process
{
int pid;
std::vector<int> memory;
};
By the way, it's a good idea to reserve use of UPPERCASE IDENTIFIERS for macros, so as to reduce the probability of name collisions with macros, and not make people reading the code deaf (it's shouting).
Cheers & hth.,
You cannot make the array (defined using []) to point to another array. Because the array identifier is a const pointer. You can change the value pointed by the pointer but you cannot change the pointer itself. Think of "int array[]" as "int* const array".
The only time you can do that is during initialization.
// OK
int array[] = {1, 2, 3};
// NOT OK
int array[];
array = [1, 2, 3]; // this is no good.
int x[] is normally understood as int * x.
In this case, it is not, so if you want a vector of integers of an undetermined number of positions, change your declaration to:
struct process {int PID;int * myMemory;};
You should change your initialization to:
int memory[2];
p.myMemory = new int[ 10 ];