Reputation: 58
I was wondering if it was okay to pass around/return structs holding statically allocated arrays in C++. For example:
typedef struct t{
char name[32];
int id;
}t;
t foo(char name[]){
t my_t = {name, 0};
return my_t;
}
int main(){
t main_t = foo("a struct");
printf("%s", main_t.name); //is this safe to access?
return 0;
}
When it returns the struct by value, I guess it doesn't copy the array name, only the pointer to it.
Edit: Just to clear up some things. I do know that char *var
is equal to char var[]
in function arguments. I wrote this code up really quickly without even testing it. I know it is definitely not the best code in the world and I wouldn't advice anybody to use it in real life.
Ideally I would allocate the struct dynamically and pass around a pointer, however, I am teaching a person to program in C/C++. It is for a national exam which doesn't require a person to know dynamic allocation or pointers for that matter, that is why *
are not really used at all.
The question is really about whether it is okay to return a struct holding a statically allocated array.
Shall we use this piece of code instead:
#include <iostream>
struct t{
char name[32];
int id;
};
t foo(int id){
t my_t;
my_t.id = id;
for(char i = 0; i < 31; i++){
my_t.name[i] = 'a';
}
my_t.name[31] = '\0';
return my_t;
}
int main(){
t main_t = foo(0);
std::cout << main_t.name; //is this safe to access?
return 0;
}
Upvotes: 0
Views: 362
Reputation: 141554
It's OK to pass around structs that contain arrays. However, this line doesn't do what you think it does:
t my_t = {name, 0};
Using designated initializer syntax, it would be equivalent to:
t my_t = { .name[0] = name; .name[1] = 0; };
The first member of t
is an array with 32 elements, so the first 32 initializers are applied to those 32 char
s. Unless you use some more braces, but you still need one initializer per element, there's no magic way to get a strcpy
out of brace-enclosed initializers.
You should get a compiler error about initializing a char
with a pointer.
Upvotes: 0
Reputation: 30136
There is no static
array in your code.
When you return a t
instance by value, it will copy the contents of the array.
The problem is with how you're initializing the t
instance, not with how you're returning it.
Change this:
t my_t = {name,0};
To this:
t my_t = {0};
strncpy(my_t.name,name,sizeof(my_t.name)-1);
Or to this, if you want to avoid the use of library functions:
int i;
t my_t;
for (i=0; i<sizeof(my_t.name)-1 && name[i]!=0; i++)
my_t.name[i] = name[i];
my_t.name[i] = 0;
my_t.id = 0;
Upvotes: 1
Reputation: 41509
It can be done.
But it shouldn't be done: alternatives are std::string
and std::array
. You get your copy, allocation, deallocation etc... for free!
struct t {
std::string name;
int id;
std::array<int, 10> integers;
};
...
t main_t = {"a struct"};
main_t.integers[5] = 5;
t copy = main_t;
assert( copy.name == "a struct" );
assert( copy.id == 0 );
assert( copy.integers[5] == 5 );
Upvotes: 2
Reputation: 32884
You've an error in your program; you're trying to copy a pointer to an array, instead you should copy the contents pointed to by the pointer into the array. It should be like this
#include <algorithm>
#include <cstring>
struct t
{
char name[32];
int id;
};
t foo(const char *name)
{
t my_t = {};
const size_t len = std::strlen(name);
const size_t max_len = sizeof(t::name) / sizeof(t::name[0]) - 1u;
std::copy(name, name + std::min(len, max_len), my_t.name);
return my_t;
}
int main()
{
t main_t = foo("a struct");
printf("%s", main_t.name);
}
As for your question
I was wondering if it was okay to pass around/return structs holding static arrays in C++
Yes, it's ok, the whole struct will get copied (or moved, depending on the type) to the variable at the calling end.
Upvotes: 0