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 ];
Related
What is the difference between this two array definitions and which one is more correct and why?
#include <stdio.h>
#define SIZE 20
int main() {
// definition method 1:
int a[SIZE];
// end definition method 1.
// defintion method 2:
int n;
scanf("%d", &n);
int b[n];
// end definition method 2.
return 0;
}
I know if we read size, variable n, from stdin, it's more correct to define our (block of memory we'll be using) array as a pointer and use stdlib.h and array = malloc(n * sizeof(int)), rather than decalring it as int array[n], but again why?
It's not "more correct" or "less correct". It either is xor isn't correct. In particular, this works in C, but not in C++.
You are declaring dynamic arrays. Better way to declare Dynamic arrays as
int *arr; // int * type is just for simplicity
arr = malloc(n*sizeof(int*));
this is because variable length arrays are only allowed in C99 and you can't use this in c89/90.
In (pre-C99) C and C++, all types are statically sized. This means that arrays must be declared with a size that is both constant and known to the compiler.
Now, many C++ compilers offer dynamically sized arrays as a nonstandard extension, and C99 explicitly permits them. So int b[n] will most likely work if you try it. But in some cases, it will not, and the compiler is not wrong in those cases.
If you know SIZE at compile-time:
int ar[SIZE];
If you don't:
std::vector<int> ar;
I don't want to see malloc anywhere in your C++ code. However, you are fundamentally correct and for C that's just what you'd do:
int* ptr = malloc(sizeof(int) * SIZE);
/* ... */
free(ptr);
Variable-length arrays are a GCC extension that allow you to do:
int ar[n];
but I've had issues where VLAs were disabled but GCC didn't successfully detect that I was trying to use them. Chaos ensues. Just avoid it.
Q1 : First definition is the static array declaration. Perfectly correct.
It is when you have the size known, so no comparison with VLA or malloc().
Q2 : Which is better when taking size as an input from the user : VLA or malloc .
VLA : They are limited by the environment's bounds on the size of automatic
allocation. And automatic variables are usually allocated on the stack which is relatively
small.The limitation is platform specific.Also, this is in c99 and above only.Some ease of use while declaring multidimensional arrays is obtained by VLA.
Malloc : Allocates from the heap.So, for large size is definitely better.For, multidimensional arrays pointers are involved so a bit complex implementataion.
Check http://bytes.com/topic/c/answers/578354-vla-feature-c99-vs-malloc
I think that metod1 could be little bit faster, but both of them are correct in C.
In C++ first will work, but if you want to use a second you should use:
int size = 5;
int * array = new int[size];
and remember to delete it:
delete [] array;
I think it gives you more option to use while coding.
If you use malloc or other dynamic allocation to get a pointer. You will use like p+n..., but if you use array, you could use array[n]. Also, while define pointer, you need to free it; but array does not need to free.
And in C++, we could define user-defined class to do such things, and in STL, there is std::vector which do the array-things, and much more.
Both are correct. the declaration you use depends on your code.
The first declaration i.e. int a[size]; creates an array with a fixed size of 20 elements.
It is helpful when you know the exact size of the array that will be used in the code. for example, you are generating
table of a number n up till its 20th multiple.
The second declaration allows you to make an array of the size that you desire.
It is helpful when you will need an array of different sizes, each time the code is executed for example, you want to generate the fibonacci series till n. In that case, the size of the array must be n for each value of n. So say you have n = 5, in this case int a [20] will waste memory because only the first five slots will be used for the fibonacci series and the rest will be empty. Similarly if n = 25 then your array int a[20] will become too small.
The difference if you define array using malloc is that, you can pass the size of array dynamically i.e at run time. You input a value your program has during run time.
One more difference is that arrays created using malloc are allocated space on heap. So they are preserved across function calls unlike static arrays.
example-
#include<stdio.h>
#include<stdlib.h>
int main()
{
int n;
int *a;
scanf("%d",&n);
a=(int *)malloc(n*sizeof(int));
return 0;
}
What I'm trying to do right now is to create an array with a length that is defined by a variable. However, when I put the variable in the array length, it gives me a "Variable length array of non-POD element type 'glm::vec2'" error. However, if I replace the variable with an actual number, the error goes away. Why does this happen and how can I fix this?
int numtriangles = sector1.numtriangles;
glm::vec2 tex[test]; //Using a variable generates an error
glm::vec3 vertices[10]; //No error here
You cannot have variable length arrays(VLA) in standard C++.
Variable length arrays are not allowed by the C++ Standard. In C++ the length of the array needs to be a compile time constant. Some compilers do support VLA as a compiler extension, but using them makes your code non-portable across other compilers.
You can use, std::vector instead of an VLA.
See this question Is there a way to initialize an array with non-constant variables? (C++)
Short answer is no you cannot directly do this. However you can get the same effect with something like
int arraySize = 10;
int * myArray = new int[arraySize];
Now myArray is a pointer to the array and you can access it like an array like myArray[0], etc.
You can also use a vector which will allow you to have a variable length array. My example allows you to create an array with a variable initailizer however myArray will be only 10 items long in my example. If you aren't sure how long the array will ever be use a vector and you can push and pop items off it.
Also keep in mind with my example that since you've dyanmically allocated memory you will need to free that memory when you are done with the array by doing something like
delete[] myArray;
Here is a little sample app to illustrate the point
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
int arraySize = 10;
int * myArray = new int[arraySize];
myArray[0] = 1;
cout << myArray[0] << endl;
delete[] myArray;
}
use STL.
IF you want a variable length array you can use vectors under #include<vector>
Native c++ array donot nave variable length array.
When you declare an array with a length specifier, only constants are allowed.
Actually it's when the program is compiled that the array length is evaluated.
Note however that it's illegal in C++ to declare int test[]; like the compiler has no way to know how much space to allocate for the variable.
Without a length specifier, there is no actual memory that is reserved for the array, and you have to resort to using pointers and dynamic memory allocation:
int * test = new int[12];
// or
int * test = new int[val]; // variable works here
// and don't forget to free it
delete [] test;
Using int test[12] actually creates an array that is statically initialized once and for all to contain 12 integers at compile time.
Do not ever attempt to do delete [] test with a variable declared this way, as it's most certainly going to make your program crash.
To be precise, if the array is declared in a function, it will use space on the program stack, and if declared in a global context, program data memory will be used.
C++ doesn't support declare variable length array. So to use a array with a length you may
Assume
a big number which is highest possible length of your array. Now declare an array of that size. And use it by assuming that it an array of your desire length.
#define MAX_LENGTH 1000000000
glm::vec2 tex[MAX_LENGTH];
to iterate it
for(i=0; i<test; i++) {
tex[i];
}
Note: memory use will not minimized in this method.
Use pointer and allocate it according your length.
glm::vec2 *tex;
tex = new glm::vec2[test];
enter code here
for(i=0; i<test; i++) {
tex[i];
}
delete [] tex; // deallocation
Note: deallocation of memory twice will occur a error.
Use other data structure which behave like array.
vector<glm::vec2> tex;
for(i=0; i<test; i++){
tex.push_back(input_item);
}
/* test.size() return the current length */
struct Test
{
int var;
char *arr;
}
int main()
{
Test a;
a.arr = new char[50];
}
The above code would create a dynamic array in the structure but the dynamic array would not be actually memory allocated within the structure, its memory would be allocated somewhere else. I want this array to be allocated in the structure as with the fixed array but I don't want to use fixed array. Any ideas?
I've tried my best to clarify my question, hope you understand.
I want to send this structure through UDP and UDP takes continues memory buffer to send that's why I want this structure to have continuous memory.
You can not do that as the new memory is from heap/ free store and your a will be allocated on stack....
you can allocate using malloc/new a continous memory block of sizeof Test + your required size and make the pointer arr to point at the end of the Test structure.
If you need it in function scope on stack you can use alloca.
Test *a = (Test*)alloca(sizeof(Test)+yoursize);
a->arr = (char*)a+sizeof(Test)...
No you cannot have variable length arrays in C++.
So you cannot do that.
You can have a fixed length array or you can use the approach you have given.
Another approach is,
You can use placement new to place your array at an pre-allocated memory location. This memory could be on stack.
Your code don't compile. You should compile it with all warnings enabled, and improve it till you got no warnings. And are your studying C or C++? If it is C++, consider using std::vector
struct Test {
int var;
char arr[1];
};
int main()
{
std::vector<char> buf;
buf.resize(sizeof(Test) + 50);
Test *foo = reinterpret_cast<Test *>(&buf[0]);
foo->arr[40] = 'b';
}
You can pass array size to structs constructor and allocate memory for array there. Don't forget to deallocate it somewhere, e.g. in destructor:
struct Test
{
int m_var;
char *arr;
public:
Test(int var) : m_var(var)
{
arr = new char[m_var];
}
~Test()
{
delete[] arr;
arr = 0;
}
};
void main(int argc, char* argv[])
{
Test t(50);
return 0;
}
Although it hasn't been "blessed" like it has in C, most compilers will still let you use the "struct hack":
struct variable_array {
size_t size;
char data[1];
};
The "trick" is that when you allocate it, you allocate enough space for the data you want to store (but this means it must be dynamically allocated):
variable_array *a = (variable_array *) ::operator new(sizeof(*a) + data_size);
a->size = data_size;
In theory, this isn't required to work -- the compiler could do a bound-check on references to the data member to ensure you don't index beyond the one element you've defined it to hold in the struct definition. In reality, I don't know of a single compiler that does such a thing, and kind of doubt that such a thing exists. Quite a lot of C code has done things like this for years, so a compiler that did such a check just wouldn't work with a lot of real-world code, even though the standard allows it. C99 also adds this (with minutely different syntax) as an official feature of the language.
Bottom line: it's a bit clumsy, but the possibility of really not working is almost entirely theoretical.
Not truly dynamic allocation, but might solve your problem (depends on if you always know the desired size of the array at compile time)
template <size_t ArraySize>
struct Test
{
int var;
char arr[ArraySize];
}
int main()
{
Test<50> a;
}
I am writing a programm in C++. In my programm I need to create an array with dynamic size inside one function, but this array should be also accessable for other functions. I will not post here my code, just write one dummy example.
char *array;
void function_1() {
array = new char(3);
array[0] = "value 1";
array[1] = "value 2";
array[2] = "value 3";
}
void function_2() {
array[0] = "new value 1";
}
int main() {
function_1();
function_2();
delete[] array;
}
My question is: I am not sure, if the array will exist outside the function_1, where it was initialised, until I delocate a memory of array.
Or the array will have just a behaviour of local variable inside one function. What means, that the memory, which stores the array values, will be dellocated after the function is finished and the memory addresses of my array can be rewroten with something else later in my programm.
Thank you.
First, of course it will exist outside, that's all what dynamic allocation is about. Also, the variable itself is global. Also, it should be a char const** array; and the allocation should be new char const*[3] (note the square brackets). The const because you won't change the contents of the strings here.
Second, don't do that. Just put it in a class and use a std::vector!
#include <vector>
class Foo{
public:
function_1(){
_array.push_back("value 1");
_array.push_back("value 2");
_array.push_back("value 3");
}
function_2(){
_array[0] = ("new value 1");
}
private:
std::vector<std::string> _array;
};
int main(){
Foo f;
f.function_1();
f.function_2();
}
Even better, have a std::vector<std::string>, so you can safely modify the contents without having to worry about memory management. Though, to this won't be a single block any more. Now I got to ask, how exactly do you want to pass the buffer to the socket?
You actually have a fatal error in your function_1(). The following code will cause array to point to a character, with the value 3. Then, it will overwrite various parts of neighboring memory, basically causing a buffer overflow.
void function_1() {
array = new char(3);
array[0] = "value 1";
array[1] = "value 2";
array[2] = "value 3";
}
What you probably want to do is create something like:
char **array;
array = new char*[3];
array[0] = new char[strlen(...)];
array[0] = strncpy(array[0], ..., strlen(...)];
// etc
A much safer and cleaner way of accomplishing this would be to do what Xeo is suggesting, and using a std::vector instead of a plain array.
Since array is global, it is visible to other functions. Memory allocated with new[] stays around until it is freed by delete[].
It will exist and be global, because the char * array pointer is global.
The memory that you allocate in function1 will stay allocated after the program exits the scope of the function and will work as expected in functions 2 and 3. Notice however, that behaviour is undefined if you call functions 2 and 3 before function one. In general though, what you're trying to do here looks like bad design, but for the sake of the question I won't bug you about that now :)
It would greatly improve the clarity of your code if you'd:
use a std::vector, especially if you plan to resize it later
use a std::string to represent strings
pass the array or vector by reference to the functions that need it.
int main() {
std::vector<std::string> vect;
function_1(vect);
function_2(vect);
}
where your functions look like:
void function_1(std::vector<std::string> & Vect)
typedefs help manage the argument types
This way you won't have to worry about leaks as the vector will deallocate itself when out of scope.
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.