How to Return Two Things from a C or C++ Function

preview_player
Показать описание
---

How to Return Two Things from a Function (C/C++) // New C and C++ programmers often wonder how to return multiple values from a single function. This video will give you some options. You can return values through pointer or reference arguments, and you can return structs and classes.

Related videos:



***

Welcome! I post videos that help you learn to program and become a more confident software developer. I cover beginner-to-advanced systems topics ranging from network programming, threads, processes, operating systems, embedded systems and others. My goal is to help you get under-the-hood and better understand how computers work and how you can use them to become stronger students and more capable professional developers.

About me: I'm a computer scientist, electrical engineer, researcher, and teacher. I specialize in embedded systems, mobile computing, sensor networks, and the Internet of Things. I teach systems and networking courses at Clemson University, where I also lead the PERSIST research lab.

More about me and what I do:

To Support the Channel:
+ like, subscribe, spread the word

Рекомендации по теме
Комментарии
Автор

I've been watching some of your videos, and as someone who started with C in the 1980's, I think you're doing a great job of communicating the fundamentals! Keep up the good work, you deserve 100x as many likes and subscribers. This is excellent instruction!

austinhastings
Автор

In C++17 and later, you can also use structured bindings:

std::vector<double> v{ 1.414, 1.618, 3.14159 };

auto [min, max] = std::minmax_element(begin(v), end(v));
std::cout << *min << ' ' << *max << '\n';

This works with tuples and structs. For example, std::minmax_element returns a std::pair, which is a struct, and assigning it to a structured binding breaks apart the struct elements, assigning them to the individual variables in the binding.

rdwells
Автор

in C++ you could also return an std::pair for 2 things
or an std::tuple for an arbitrary number of things

I personally like the simple C way of doing things (returning a struct)

lordadamson
Автор

Summary for people who are in a rush.

How to return 2 things?
1. Make a struct or class and return that single thing.
2. Get a some pointers(or reference if you do cpp) as arguments and write the data to that location.

You could also return a single array which contains those 2 things...

frozentomatoman
Автор

Thank you, Jacob. Again, this is a very worthwhile topic.
I have three annotations:
- The values pointer can be made const to make it clear that these are input values.
- The loop can start at 1 rather than 0.
- The second check is not needed if the current value is bigger than max, which transforms the two if-clauses into an if-else/if-clause.
But the last two items will seldomly have practical impact.
However, the const correctness is a thing which I learnt to like over the last years. - This would also be a topic for another video. ;-)
Take care!

michaelkotthaus
Автор

When using the return pointer approach I like to prepend the pointer name with "ret_" or "out_".

ryantmulligan
Автор

I learned (at school) to avoid passing structs by value because of the limitations of the first compilers, but it's been fine for a couple of decades!
That said, if the struct is large it's not optimal to return it, and so passing its address using an argument (a pointer) is preferable.
But the danger with returning a struct is when the struct contains any member which has a address of a local variable (that's a bug, but not an easy one to find for a beginner)
One more thing: struct are copied using gcc's builtin memcpy, and that can be a problem on some embedded systems, depending on how the toolchain has been setup (if you screw-up the build of the cross-compiler)

unperrier
Автор

Some more ideas for C++: std::array, std::vector, std::tuple, std::pair. But in my opinion, struct is the best way because you can have named variables.

aramayisorkusyan
Автор

I like the passing in pointers aproach and using a return value for error handling like returning a simple bool or an int used as a bitset

attilatorok
Автор

One interesting thing that is done in embbeded C is structure packing for example to send a float through a UART which is just a uint8_t "char" at a time, you can pack a structure with all kinds of data and send out the structure byte by byte and reassemble at the other end., Or just send the float itself byte.by byte and reassemble at the other end. Though struct packing is not "portable" I've still havent had an instance where it doesn't work

EdwinFairchild
Автор

I like the idea of structs, also because it would make for possibly beautiful error handling in C, which I generally find a little difficult in that language.

drvanon
Автор

C++ also has structs, which acts like classes(have member functions). There is only one difference between class and struct. Struct is public by default, so in case, which you presented, struct is better than class, because you don't need to write "public" section :) The main convention is using structs for simple objects, like PODs and using classes for more complex.

piotrs
Автор

since you cannot throw in C, I usually use the return-value as error-code, which means I prefer passing pointers and let the return-value report potential errors.

SimonJentzschX
Автор

Currently learning C. Great video. Thanks. 👍

benjaminrich
Автор

Returning a structure is often frowned-upon because when the structure is large (more than 8 bytes on some processors), the CPU has to make a memcpy call. This is because on some computers (such as 32-bit ARM devices) only two 32-bit registers are used for return values. Often only one register is used as such. Memcpy is slow and expensive and scales poorly if the structure grows in size. You want your functions that use structures and param or return types to not have to worry about the shape or size of that struct (abstract data types are good practice for maintainability and readability).

As such is is recommended to pass in a pointer to a struct if using it as a param. You can document the function params as in or out or inout to make the direction clear.

To see why returning a structure is bad practice, see this:

typedef struct { ... } MyType;

MyType foo(int i, short s, _Bool b) { ... }

int main()
{
MyType x; int i; short s; _Bool b; // local variables
// Do stuff to compute and assign i, s and b
x = foo(i, s, b);
// Do stuff with x
return 0;
}

In the above, the function has to (a) create a MyType struct (for x), and then (b) create a MyType struct (internally in the local foo function) and then (c) copy all the data from the local foo return value into the x variable. Notice also that the foo function signature is at least as large as the MyType struct, which could be gigabytes in size for all we know!! That's a huge waste of space.


A drastically faster way to do the above would be as follows:

#define IN // empty macro to document read-only param
#define OUT // empty macro to document write-only param (a return value in a function). The param must be a pointer to "pass by reference"
#define INOUT // empty macro to document a param that is in and out in direction. Param must be a pointer type.
typedef struct { ... } MyType;

foo(IN int i, IN short s, IN _Bool b, OUT MyType *x) { ... } // this style is esentially passing a parameter by reference for modification

int main()
{
MyType x; int i; short s; _Bool b; // local variables
// Do stuff to compute and assign i, s and b
foo(i, s, b, &x);
// Do stuff with x
return 0;
}

This approach uses step (a) from above, but none of the other steps. Also the function signature is now just a few bytes long (as the type MyType* is 4 or 8 bytes long only).

gregoryfenn
Автор

Tfw when you could shorten this video to literally 10 seconds

kangalio
Автор

With std::tuple it'd be: auto [min, max] = get_max_and_min(values, 5);
and return would be: return {min, max};
function signature is: tuple<double, double> get_max_and_min(...)
That's what I was expecting to see you show once you got to C++ actually

AinurEru
Автор

So much useful information for a real job. Thanks

YuanweiLao
Автор

Yay nice vid.
Programming is superpower.

frozentomatoman
Автор

best is return a boolean or a number for such functions supplying addresses of pointers. Love your channel

davidramsay