Struct as function parameter

I have been using the following way of passing a structure to a function

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>
#include <cstring>

using namespace std;

struct datast
{
	int a,b;
	string text;
	int ar[6];
	int *ptr;
};

void display(datast st)
{
        st.a=0;
  	cout << "a=" << st.a << endl;
	cout << "b=" << st.b << endl;
}

int main(){
	struct datast s;
  	s.a = 4;
	s.b = 5;
  	display(s);
	return 0;
}


I came up with it by trial-and-arror. A tutorial found here https://www.codesdope.com/cpp-structure/ showed me another way (several ways) but not mine so I'm not sure why it worked. I wouldn't want to risk any undefined behavior.

This is a method from the tutorial

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>
#include <cstring>

using namespace std;

struct datast
{
	int a,b;
	string text;
	int ar[6];
	int *ptr;
};

void display(struct datast *st)
{
        st->a=0;
  	cout << "a=" << st->a << endl;
	cout << "a=" << st->b << endl;
}

int main(){
	struct datast s;
  	s.a = 4;
	s.b = 5;
  	display(&s);
	return 0;
}


Differences:
I passed s rather than &s.
The function received "datast st" rather than "struct datast *st".
I used dots rather than ->.

Both methods produced the same results. Why didn't mine fail? Does it happen to be also correct? The structure in general has also arrays and pointers that may be used later.
Last edited on
First method passes the struct "by value", effectively passing a copy of the original struct.

Second method passes a pointer to the struct, i.e. the struct is passed "by reference", no copy is created.

Both methods are legit, but passing a pointer can be more efficient, especially for "big" structs.

Also be aware that, if you pass a pointer, then any changes you make to the struct inside the function are reflected in the original struct! This would not the case when passing the struct "by value".
Last edited on
I missed something. I now added an instruction modifying a within the function. The original structure changes in both cases. The behaviour is the same. It could not be passing by value which is why I think it might be undefined behavior.
If you pass the struct "by value", then you can, of course, modify the local copy inside the function.

The changes are then visible where the local "copy" is used, but they will not effect the original struct at all!

Meanwhile, if you pass a pointer, then you'll read/modify the original struct, even inside the function.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>

struct datast
{
    int a;
};

void foo(datast st)
{
    st.a = 42;
    std::cout << "foo: " << st.a << std::endl;
}

void bar(datast *st)
{
    st->a = 42;
    std::cout << "bar: " << st->a << std::endl;
}

int main() {
    struct datast s;
    s.a = 0;
    foo(s);
    std::cout << "main: " << s.a << std::endl; // <-- "0"
    bar(&s);
    std::cout << "main: " << s.a << std::endl; // <-- "42"
}
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// For “in” parameters, pass cheaply-copied types by value and others by reference to const
// https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rf-in

struct A { std::string str ; std::vector<double> data ; };
void print( const A& ) ;

struct B { int first = 0 ; int second = 9 ; };
void print( B ) ; // pass cheaply-copied types by value


// For “in-out” parameters, pass by reference to non-const
// https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rf-inout
void update( A& ) ;


// For “out” output values, prefer return values to output parameters
// https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rf-out
A make_A( double x, double y ) ;


// Prefer T* over T& when “no argument” is a valid option
// https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rf-ptr-ref
void update_if( A* pa ) ; // if pa == nullptr, there is no A 
Topic archived. No new replies allowed.