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

  Рет қаралды 36,843

Jacob Sorber

Jacob Sorber

3 жыл бұрын

Patreon ➤ / jacobsorber
Courses ➤ jacobsorber.thinkific.com
Website ➤ www.jacobsorber.com
---
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:
Pointers/Arrays: • Arrays, Pointers, and ...
Pthreads: • How to create and join...
***
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:
www.jacobsorber.com
people.cs.clemson.edu/~jsorber/
persist.cs.clemson.edu/
To Support the Channel:
+ like, subscribe, spread the word
+ contribute via Patreon --- [ / jacobsorber ]
Source code is also available to Patreon supporters. --- [jsorber-youtube-source.heroku...]

Пікірлер: 167
@austinhastings8793
@austinhastings8793 3 жыл бұрын
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!
@rdwells
@rdwells 3 жыл бұрын
In C++17 and later, you can also use structured bindings: std::vector v{ 1.414, 1.618, 3.14159 }; auto [min, max] = std::minmax_element(begin(v), end(v)); std::cout
@ruadeil_zabelin
@ruadeil_zabelin 3 жыл бұрын
Don't allocate on the heap just to return something. Then at least use a tuple. std::make_tuple(1, 2.0f, 12345);
@frozentomatoman3422
@frozentomatoman3422 3 жыл бұрын
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...
@iuppiterzeus9663
@iuppiterzeus9663 3 жыл бұрын
when returning an array make sure it's not on the stack but on the heap (using malloc or something similar). it may still work correctly (if on stack), but this is technically undefined behavior and can lead to segmentation faults.
@malusmundus-9605
@malusmundus-9605 2 жыл бұрын
I call an array with 2 elements a Kit-Kat : D
@truberthefighter9256
@truberthefighter9256 2 жыл бұрын
Okay, I forgot that last option. But I am kinda sad... because I already knew those approaches, and I was hoping for any better xD
@Victor_Marius
@Victor_Marius 2 жыл бұрын
@@malusmundus-9605 or tuple
@Victor_Marius
@Victor_Marius 2 жыл бұрын
Returning an array you are limited to using the same type for all returning variables. The struct method is better for the programmer and the pointer method for the machine - when you are dealing with low memory (I would say)
@lordadamson
@lordadamson 3 жыл бұрын
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)
@yakinbama
@yakinbama 2 жыл бұрын
Yep… these came to mind first when he mentioned C++ options!
@fullfungo
@fullfungo Жыл бұрын
But… std::tuple *is* a struct tho.
@michaelkotthaus7120
@michaelkotthaus7120 3 жыл бұрын
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!
@JacobSorber
@JacobSorber 3 жыл бұрын
Yes, indeed. Thanks, Michael.
@ryantmulligan
@ryantmulligan 3 жыл бұрын
When using the return pointer approach I like to prepend the pointer name with "ret_" or "out_".
@aramayisorkusyan
@aramayisorkusyan 3 жыл бұрын
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.
@johnstanp9692
@johnstanp9692 2 жыл бұрын
The last solution is the one I've come to prefer: it adds more clarity to what is returned (with a pair or a tuple you have to remember what is associated with what) and it leaves room for "extension". You can add more variables to return and you won't be forced to change the signature of the function or to overload it...
@matthewskipworth962
@matthewskipworth962 Жыл бұрын
Yes! I saw “How to return two things” and thought the obvious answer was std::pair.
@unperrier5998
@unperrier5998 2 жыл бұрын
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)
@EdwinFairchild
@EdwinFairchild 3 жыл бұрын
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
@JacobSorber
@JacobSorber 3 жыл бұрын
Argument marshaling is a lot of fun. Might make a good topic for a future video. Thanks.
@benjaminrich9396
@benjaminrich9396 3 жыл бұрын
Currently learning C. Great video. Thanks. 👍
@attilatorok5767
@attilatorok5767 3 жыл бұрын
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
@TheCocoaDaddy
@TheCocoaDaddy 3 жыл бұрын
Great video! Thanks for posting!
@kangalio
@kangalio 3 жыл бұрын
Tfw when you could shorten this video to literally 10 seconds
@tahirsengine
@tahirsengine Жыл бұрын
Definitely worthed watching.
@YuanweiLao
@YuanweiLao 3 жыл бұрын
So much useful information for a real job. Thanks
@AinurEru
@AinurEru 2 жыл бұрын
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 get_max_and_min(...) That's what I was expecting to see you show once you got to C++ actually
@frozentomatoman3422
@frozentomatoman3422 3 жыл бұрын
Yay nice vid. Programming is superpower.
@gregoryfenn1462
@gregoryfenn1462 3 жыл бұрын
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).
@yttos7358
@yttos7358 2 жыл бұрын
Love the video! In C++ the struct keyword can be used in place of the class keyword. The only difference between the two is fields are private (by default) in classes and public (by default) in structs. So using a class here for a `struct`ure of data leads me to believe a struct would have been better anyway.
@drvanon
@drvanon 3 жыл бұрын
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.
@SimonJentzschX7
@SimonJentzschX7 3 жыл бұрын
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.
@nandomax3
@nandomax3 3 жыл бұрын
That's a nice strategy
@Kotesu
@Kotesu 3 жыл бұрын
That is/was considered best practice within the circles of embedded development that I worked in for the past decade and a half. I've experimented with a few different options but thus far I hadn't found anything that matched the simplicity, flexibility and consistency over a product lifecycle.
@unperrier5998
@unperrier5998 2 жыл бұрын
that's my go-to approach as well.
@dmitripogosian5084
@dmitripogosian5084 Жыл бұрын
Yes, if there are several variables to return and you have several pointers in the argument, there is no sense to use function return to make one of those special, I also use it for error codes
@davidramsay9321
@davidramsay9321 3 жыл бұрын
best is return a boolean or a number for such functions supplying addresses of pointers. Love your channel
@piotrs7632
@piotrs7632 3 жыл бұрын
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.
@mehdi-vl5nn
@mehdi-vl5nn 3 жыл бұрын
struct is a c things, nowadays structs in cpp are considered as class i remember several years ago i wrote a struct in cpp and had a err in it and compiler was like class blah blah
@IvanSchob
@IvanSchob 2 жыл бұрын
Thanks it helped
@TNothingFree
@TNothingFree 3 жыл бұрын
Either struct or structural bindings, You can use "Using" alongside for readability: using ParseResult = std::pair; ParseResult Parse(...); auto [a,b] = ParseResult();
@SandipBhattacharya
@SandipBhattacharya Жыл бұрын
How to return multiple values from a C/C++ function? Usually, a function can only return a single value, using the return mechanism. If you try to return more than one value from a function, only one value will be returned that appears at the rightmost place of the return statement. However, you can return multiple values from the function using the pointer, array, or structure. Using Pointers You can use pointers to return more than one value from a function by passing pointers as function parameters and use them to set multiple values which will then have visibility in the caller function. Using Array If you want to return multiple values of the same data type from a single function, then using an array is best suited because when an array name is passed as an argument then its base address is passed to the function so whatever changes made to the array is changed in the original array. Using Structure Another way to return multiple values from a function is by using structures. Structure is a user-defined datatype in C that can hold several datatypes of the same or different types. The idea is to create a structure variable containing all required data types as its members and return that from the function. We can then retrieve the values from the structure variable inside our caller function.
@xCwieCHRISx
@xCwieCHRISx Жыл бұрын
Just passing and returning pointers (or reference) and basic datatypes is good practice, because all arguments at function call and the return value gets copied and structs and arrays have bigger size than pointers.
@jonbezeau3124
@jonbezeau3124 Жыл бұрын
I'm really not in love with stuffing output into function parameter pointers, but it has a few advantages: one good thing to come of it is that it forces your functions to properly use const modifiers for input-only params, and another is that the pointers you're modifying can be references to stack-allocated storage. The thing I prefer about returning struct is first that you're using return values to return results, and secondly the rest of the program might use structs to organize values that might be kept in unrelated variables. I guess if the structs start getting big and unweildly, the next level is to dynamically allocate them and return just the pointer.
@otmanm4095
@otmanm4095 3 жыл бұрын
Awesome!
@wedusk
@wedusk 3 жыл бұрын
std::pair or std::tuple (for different types)
@nilrem999
@nilrem999 Жыл бұрын
Love your videos! In this video, you populate a struct in the get_min_max function, which is returned to the caller, not using pointers. How is this done? Is it going via the stack? I guess my question would be: How does a function return its return value to the calling function without using pointers? If this question is not worth a whole video, could you maybe point me to a source which will clarify this?
@mahmednabil2429
@mahmednabil2429 3 жыл бұрын
we could also use tie() and pair in c++ to simulate python or ruby
@mlecz
@mlecz Жыл бұрын
No, tie returns references, so in this case using tie can cause undefined behavior. You should use make_tuple instead.
@cameronball3998
@cameronball3998 3 жыл бұрын
I had to pop a stack in C++ for an assignment in college and return the popped value. If I only had this video back then... would’ve saved me an hour of research to figure this out lol (that I could return it because the parameter was passed by reference)
@davidramsay9321
@davidramsay9321 3 жыл бұрын
Most best is functions return numbers (c can return size_t as any type you want) but address of a type in a function is nice especially for re-entrant code. void func (void ***array, char **buffer) == address of an array and address of buffer and array to be populated.. Pointers are hard for some...
@journeyman6856
@journeyman6856 3 жыл бұрын
Could you make a video about how to run console commands from withing C++? How to use ShellExecute(), System(), etc
@konstantinrebrov675
@konstantinrebrov675 3 жыл бұрын
You should have mentioned a common mistake that beginners make: ``` void get_max_and_min(double* values, int length, double* pmin, double* pmax) { assert(length > 0); double max = values[0]; double min = values[0]; for (int i = 0; i < length; i++) { if (values[i] > max) max = values[i]; if (values[i] < min) min = values[i]; } pmin = &min; pmax = &max; // See it works! printf("min = %d ", *pmin); printf("max = %d ", *pmax); } ``` Instead of dereferencing the pointer and setting the value, beginners might set pmin to point to min and set pmax to point to max. That is often happens. In such situation we are modifying only the parameters which are local variables, to point to the max and min. Although if we print the value in the function everything appears fine. But when the function returns the pointers pmin and pmax expires and the values min and max also expires.
@LingvoScienceUSA
@LingvoScienceUSA 7 ай бұрын
It would be interesting to know, how exactly the compiler handles references as a pointer. Apparently it must refer to function prototype to generate according calling machine code. Otherwise how could it know that it must pass address but not value?...
@dogukan463
@dogukan463 3 жыл бұрын
It might not be a popular topic but I'd like to see a video about preprocessor directives especially code generation/macro expansion I don't know the exact term but it made me scratch my head when I looked into it.
@JacobSorber
@JacobSorber 3 жыл бұрын
Yes, I've had preprocessor stuff on my topic list for a while now. It's definitely an interesting topic. I'll see what I can do.
@dogukan463
@dogukan463 3 жыл бұрын
@@JacobSorber thanks for the effort, greatly appreciated :)
@TarousDT
@TarousDT 2 жыл бұрын
I'm going to write a function that takes in a byte array buffer and fills it with whatever and you have to properly interpret the bytes it returns into whatever data you are expecting.
@muzafferirmakyavuz9993
@muzafferirmakyavuz9993 3 жыл бұрын
Please explain wrapper functions with function pointer in c sir. Purposes etc.
@jadanabil8044
@jadanabil8044 3 жыл бұрын
Please make a video about synchronisation, concurrency and parallelism using while dealing with threads.🙏
@JacobSorber
@JacobSorber 3 жыл бұрын
I talk a little about this in my thread videos. If you've already checked those out, I would love to hear, specifically, what you think I'm missing and would like to hear more about. Thanks.
@HimanshuSharma-sd5gk
@HimanshuSharma-sd5gk 3 жыл бұрын
Plz plz answer this question sir.. For passing multidimentional array to function how valid is to use void function(int x, int y, int array[x][y]); This worked fine on my system. I am himanshu sharma from india
@AlexJacksonSmith
@AlexJacksonSmith 2 жыл бұрын
OK, now I understand. The first option is comfortable to COBOL people as this is what we do all the time. One method of clearing that up for C thinkers would be to "name" the parameters as resultMAX, resultMIN. That would clear up confusion if the people can't keep track of what data is for what. I am not yet fully comfortable using pass by value, as in COBOL we would often want the new value to overwrite the old. I guess the struct is actually returning a pointer to the structure and not the values of the structure? If so it is still call by reference but visually separated in the code listing... seems to me this is only important for a programmer to cope with remembering rather than efficiency or reliability. If I have misunderstood the reasoning another video could be helpful. Thanks A.,
@Voltra_
@Voltra_ 3 жыл бұрын
Talking about std::pair or std::tuple would have been a nice addition
@davidramsay9321
@davidramsay9321 3 жыл бұрын
Or more, address if a return variable can be populated or return a populated struct.
@yagami-light
@yagami-light 3 жыл бұрын
you can use a static array and return array
@Beatsleigher
@Beatsleigher 3 жыл бұрын
Genuinely surprised there is no mention of pairs, tuples, etc. If I need more than one return value which doesn't justify a whole class (IMO if you use a class, use encapsulation), I'll use something from the STL. A tuple is perfect for this kind of operation, as I can always add more values if necessary during development or as an update to the software. Whereas if I create a class for it, I'll need to add getters, setters potentially even add logic to the destructor if the data requires it. Another option here would be a smart pointer (shared_ptr, unique_ptr) depending on your use-case. Nonetheless I like the way your videos address junior programmers. Keep it up, I've learned some things from you, too.
@44r0n-9
@44r0n-9 3 жыл бұрын
I think the reason he didn't cover these are because they are C++ exclusive
@Beatsleigher
@Beatsleigher 3 жыл бұрын
@@44r0n-9 But so is passing references and using classes.
@JacobSorber
@JacobSorber 3 жыл бұрын
Thanks. And, yes that's a fair point. You definitely can use the STL. And, pairs and tuples are simply templated classes. So, I guess, that falls under the return-a-class option. But, mostly it was about what I had time for. Maybe pairs and tuples need a follow-on video. 🤔
@Beatsleigher
@Beatsleigher 3 жыл бұрын
@@JacobSorber That's a fair point with the return-a-class, but it's a more viable option IMO, because they take the majority of the work from you.
@JacobSorber
@JacobSorber 3 жыл бұрын
​@@Beatsleigher Very true.
@marusdod3685
@marusdod3685 3 жыл бұрын
if you know how to take advantage of the preprocessor you can kinda create your own syntatic sugar: #define DEF_TUPLE(T,U)\ struct TUPLE_ ## T ## _ ## U{\ T first;\ U second;\ } #define TUPLE(T,U)\ struct TUPLE_ ## T ## _ ## U DEF_TUPLE(int,char); TUPLE(int,char) fun(){ return (TUPLE(int,char)){5,'a'}; } int main(){ TUPLE(int,char) a = fun(); printf("%d %c ",a.first,a.second); } the drawback is you have to define a different tuple for every combination. you can also use this to define matrices of different sizes
@NotMarkKnopfler
@NotMarkKnopfler 3 жыл бұрын
Hang on... The result struct (of type 'number_range') is declared local to the function. In other words, it's on the stack. Doesn't it go 'out of scope' when the function returns? I never use this technique for this reason. Anyone?
@ohwow2074
@ohwow2074 3 жыл бұрын
No you can easily return a local struct and use it in the caller’s body.
@srijanpaul
@srijanpaul 3 жыл бұрын
Ideally, use std::pair in C++ instead of that struct. In C there's no pairs but one could do templated pair using macros I guess.
@ep9017
@ep9017 3 жыл бұрын
std::tuple could be used aswell
@JacobSorber
@JacobSorber 3 жыл бұрын
Yes, you definitely could. Thanks.
@hapashreguiem7460
@hapashreguiem7460 3 жыл бұрын
@@ep9017 tuple works for three things only
@mshingote
@mshingote 3 жыл бұрын
For more than two elements std::pair gets ugly. Struct/class is more clean!
@srijanpaul
@srijanpaul 3 жыл бұрын
@@mshingote right, but the video title said "Return two things" so it was in reference to that.
@ruadeil_zabelin
@ruadeil_zabelin 3 жыл бұрын
Try to avoid arguments with side-effects as much as possible. We shouldn't be teaching new programmers to do something like that. In your example I'm also missing the proper usage of const. There is no indication from your function which variables are actually going to get changed. double * values is passed in non-const, this tells me your function changes it; which it doesn't, so make it const. Another thing, if you're passing multiple values like this, the C++ core guidelines say that you should never have a pointer and then a size; this is old C style which really should be avoided. You can pass a span instead: std::span. This will create a "view" on an existing buffer that includes the size which makes it impossible, at least in the context of this function, to have a mismatch between the size and the data. Also don't code with specific types. Now you have to write the same function again for a float and an int if you need it. You can make this templated. Whenever you need an algorithm like this, check if there isn't already a standard function to do this. In your case, you could've used std::min_element and std::max_element. Another thing is that if you're sure your function does not throw, mark it as noexcept. This allows for better optimization and also gives you a warning when you are potentially leaking an exception out of your function when you don't expect it. When all is said and done, here is the full function: template auto myfunc(const std::span &values) noexcept -> std::tuple { return {std::min_element(std::begin(values), std::end(values)), std::max_element(std::begin(values), std::end(values))}; } Since C++11 there is also std::minmax_element which does exactly what you do here: template auto myfunc(const std::span &values) noexcept { return std::minmax_element(std::begin(values), std::end(values)); } Since C++20 you can even do this: auto myfunc(const std::ranges::input_range auto &values) noexcept { return std::minmax_element(std::begin(values), std::end(values)); } Can be called/used like this: std::vector h{1,2,3,4}; auto [min, max] = myfunc(h); min and max are now regular variables.
@shaytal100
@shaytal100 3 жыл бұрын
Smart to initialize min/max with values[0]. But shouldn't you then start the for loop with i=1 ?
@unperrier5998
@unperrier5998 2 жыл бұрын
Totally, but that's not a big problem, at least that's not a functional issue.
@afborro
@afborro 2 жыл бұрын
C++ return std::pair. From what I've seen so far, i think your C tuts are great (mine is a bit rusty seeeing I never looked back once I went C++) , but you are doing too much C style in C++. Just my O2.
@TheVralapa
@TheVralapa 3 жыл бұрын
std::make_pair + structured binding to unpack! :)
@myusernameislongerth
@myusernameislongerth 3 жыл бұрын
5:50 "direction of information is not so clear". Well, this is what const can make clearer - stuff that goes in is const, and the suff that is not const goes out.
@rishabhanand4270
@rishabhanand4270 3 жыл бұрын
A few people might find this video looking for an explanation on how the fork system call returns two values. Well, it doesn't return two values, it returns the process ids to the appropriate processes. After the fork, there are multiple processes running the same code, and hence fork returns the pid of the child to the parent process and 0 to the child process.
@konstantinrebrov675
@konstantinrebrov675 3 жыл бұрын
fork() returns one value only, but it returns one value into first process, and a different one value into second process.
@shushens
@shushens 3 жыл бұрын
Why not just use a clang-format file? You can re-use the same on every time 🙂
@kellingc
@kellingc Жыл бұрын
Now, in Pascal, arrays are referenced, as are strings, And in C it seems as though you'd have the same thing. So if they re the same type, and you pass an array in, then whatever you put into the cells would be set globally. This is both elegant, and kludgy at the same time, You are modifying a global variable from within a function, This can be dangerous, but if you keep track of what you are doing and specify that the return values are in the array, then it should be good to go. I do like using the struct as a return value, and often do so with my pascal functions. Procedures are another matter, as they don't return anything, but you put the VAR keyword in front of the parameter variable to make it a reference instead of pass_by_value. This is used in Turbo Pascal (and Free Pascal) procedures like getdate and findfirst. Anyway, not so much a question or any insight, just a comment, I guess. It helped my think out what's goig on, and giving me ideas on how to improve both my C and pascal coding.
@LinucNerd
@LinucNerd 3 жыл бұрын
Structs / Classes are prettier, but pointers are more flexible. I don't know C++, but you mentioned that with references, you can't pass NULL? So, no optional argument I guess... Probably has some nice uses, but I don't quite see where that would be useful (Not saying there aren't any, just confused as to why they exist).
@SirRebonack
@SirRebonack 3 жыл бұрын
References aren't really pointers. They can behave like pointers under the hood, but aren't guaranteed to do so. In many cases they're just an alias for the variable assigned to it. This requires that they cannot be null, which is why a reference must always be initialized.
@weremsoft
@weremsoft 3 жыл бұрын
Please, make a video about SIMD.
@TomStorey96
@TomStorey96 2 жыл бұрын
Look up Creel. He does a lot of x86 assembly.
@andydelle4509
@andydelle4509 3 жыл бұрын
I once did a trick where I needed two return variables but they were 8bit unsigned char only. I simply returned an unsigned int and stacked one byte with a multiply by 0x100. Then the receiving function simply broke the unsigned int back apart.
@JacobSorber
@JacobSorber 3 жыл бұрын
Yeah, that would work. Thanks.
@rustycherkas8229
@rustycherkas8229 2 жыл бұрын
Could have used a union instead. typedef union { unsigned char indmin, indmax; short int bothminmax; } bytePair_t; short int minmax( int arr[], int len ) { bytePait_t result; result.indmin = index of min val in array result.indmax = index of max val in array return result.bothminmax; } Your code 'knows' how you've stacked two bytes together. This code uses conventional C to achieve the same effect. You could 'stack' as many as 8 bytes if the union contains a double. Be sure to document this 'trick' used to skirt limitations of old compilers. Of course, the size of a byte sets a limit on the range (0-255).
@Nick-cv4ci
@Nick-cv4ci 2 жыл бұрын
I want someone to love me how Jacob loves makefiles
@alexwexov4298
@alexwexov4298 3 жыл бұрын
What about std::pair ?
@ArtemijSmyslovskij
@ArtemijSmyslovskij 3 жыл бұрын
In modern c++ you're supposed to return std::tuple or std::pair
@mogenshansen7210
@mogenshansen7210 2 жыл бұрын
I think, in general, that your examples are much more C style than C++ style (notice that that there are no language called C/C++) I more idiomatic C++ example would used std::pair or std::tuple - as multiple has noted and structured binding for the called. An idiomatic C++ example would also use an iterator pair, begin and end, like all the C++ Standard library algorithms, rather than a pointer and a length. Outputting the result will idiomaticly also be done in a more type safe, expandable way than using printf From there it is trivial to turn the algorithm into a generic function, which can handle sequences of any assignable and comparable type (like int, double, std::string, std::pair etc) not just doubles, and any (forward) iterator types thus supporting many different container types (like C array, std::array, std::vector, std::list etc) and not just elements in contiguous memory #include #include #include #include #include #include #include template constexpr auto get_max_and_min(IterT begin, const IterT end) { using ElemT = std::remove_cv_t; ElemT max { begin != end ? *begin : ElemT{} }; ElemT min { begin != end ? *begin : ElemT{} }; while(begin != end) { max = std::max(*begin, max); min = std::min(*begin, min); ++begin; } return std::make_tuple(max, min); } int main() { { // double values in an array constexpr std::array values {9.8, 1.2, -75.2, 14.0, 3.0 }; const auto [max, min] { get_max_and_min(values.begin(), values.end()) }; std::cout
@ohwow2074
@ohwow2074 3 жыл бұрын
There’s also the std::tuple which can be returned by value.
@JacobSorber
@JacobSorber 3 жыл бұрын
Indeed. I was mentally sticking that into the return-a-class category, but it would have been good to point out. Thanks!
@kelvinxg6754
@kelvinxg6754 3 жыл бұрын
seems like your channel is mostly demonstrated in c do you have any reasons why? anyways your content is good as always.
@JacobSorber
@JacobSorber 3 жыл бұрын
Thanks. A lot of my teaching (operating systems) is in C. And, I do research on low-power embedded systems. So, a lot of that uses C (or C++). And, I think C is a decent language for helping new programmers understand how computer software works. It's simple enough that the language doesn't usually get in the way. So, I guess that's as close to a good reason as I've got.
@kelvinxg6754
@kelvinxg6754 3 жыл бұрын
@@JacobSorber thank you now i get it My first language was c++ if i were started with python I would be so confused Keep doing what you doing it’s really great stuff i always checking your stuff when it comes to review and refresh my knowledge .
@nandomax3
@nandomax3 3 жыл бұрын
why does c++ functions usually have as argument the array and the length of the array? Is it possible to set as arguments of a function just the array? I'm new to C++
@XxBobTheGlitcherxX
@XxBobTheGlitcherxX 3 жыл бұрын
When you pass an array you are really just passing a pointer. A pointer does not know how big the block of data its looking at and so you have to send its size with it. You can use std::array or std::vector, if you dont want to use built-in arrays.
@nandomax3
@nandomax3 3 жыл бұрын
@@XxBobTheGlitcherxX Thanks! Now I got it
@brdrnda3805
@brdrnda3805 2 жыл бұрын
Off-Topic: I would start the for loop with int i = 1. Is that hurtful to C-programmers?
@xCwieCHRISx
@xCwieCHRISx Жыл бұрын
char arr[] = {1,2,3,4,5,6,7,8,9,10}; for (int i=1; i < sizeof(arr)+1; i++) printf("%d ", arr[i-1]); vs for (int i=0; i < sizeof(arr); i++) printf("%d ", arr[i]); what do you think is more hurtful?
@brdrnda3805
@brdrnda3805 Жыл бұрын
@@xCwieCHRISx That's not the point. The code in the video is double max = values[0]; double min = values[0]; for (int i=0; i < length; i++) { if (values[i] > max) max = values [i]; if (values[i] < min) min = values [i]; } When you start the loop with 0 you compare the value in the array in the first iteration with itself. That's unnecessary. Therefore double max = values[0]; double min = values[0]; for (int i=1; i < length; i++) { if (values[i] > max) max = values [i]; if (values[i] < min) min = values [i]; } is better... in my opinion.
@glowiever
@glowiever 3 жыл бұрын
I really am stuck at c++98. any practice to imprint the current stuffs?
@JacobSorber
@JacobSorber 3 жыл бұрын
Are there any features that you are specifically trying to pick up?
@glowiever
@glowiever 3 жыл бұрын
@@JacobSorber I still can't get lambdas. too verbose of a syntax and I dunno when to use it. can't wrap my head around it.
@arson5304
@arson5304 3 жыл бұрын
@@glowiever thecherno has a pretty informational video on lambdas: kzfaq.info/get/bejne/o72XoKVz35bdaJc.html i'd also recommend that you check out jason turner's videos on c++ lambdas, he also has hundreds upon hundreds of videos on more modern c++ features kzfaq.info/sun/PLs3KjaCtOwSaJfzcaQ5RpcDIx9PTe2bBP
@hasanalattar9561
@hasanalattar9561 2 жыл бұрын
like the video as always, but i have to point out that it hurts me to see the style of pointer (double **ptr) (double * values) (double** ptr) .. all in one line :(
@iandmetick07
@iandmetick07 3 жыл бұрын
Struct pointer
@boxedowl
@boxedowl 3 жыл бұрын
For some reason I never stopped to check and see if Python was just packing and unpacking tuples under the hood and the return multiple args wasn't just syntactic sugar... the lies!
@skilz8098
@skilz8098 3 жыл бұрын
The Python Interpreter is written and based on the C language. Now, the language and it's syntax is quite different, but under the hood, it's still C based, except that it is also an interpreted language and not a compiled one.
@WistrelChianti
@WistrelChianti 2 жыл бұрын
I feel so trolled by the title of this video X'D. Came here thinking "er... you can't RETURN more than a single THING from a function" having seen the video, I see this is still the case (but yes of course that thing can contain other things or indeed you can pass multiple parameters by reference instead of value or pass pointers), this isn't the same as RETURNING more than one THING though... that's impossible.
@arielspalter7425
@arielspalter7425 3 жыл бұрын
Aren't there tuples in c++? It's a viable option for a quick and dirty solution in C#.
@anthonynjoroge5780
@anthonynjoroge5780 3 жыл бұрын
Yes there are
@taragnor
@taragnor 3 жыл бұрын
Well yes and no. C++ doesn't natively support tuples the way Rust and Python do. A C++ tuple (std::tuple) is basically just a templated class that you create. Essentially saves you the boiler plate of having to declare a custom struct/class that contains the data you want to return.
@alexcipriani6003
@alexcipriani6003 3 жыл бұрын
before I watch the video....make return a struct?
@BetaChri5
@BetaChri5 3 жыл бұрын
my guess is pointers
@alexcipriani6003
@alexcipriani6003 3 жыл бұрын
@@BetaChri5 well a pointer points to something it cannot hold the “two things” the question he is trying to answer here is how you return more than one thing when one is the standard
@srijanpaul
@srijanpaul 3 жыл бұрын
@@alexcipriani6003 two pointers as args
@alexcipriani6003
@alexcipriani6003 3 жыл бұрын
@@srijanpaul to be fair that’s not “returning” that’s modifying variables using a function but same effect. He said return so I was focusing on the “return”...
@srijanpaul
@srijanpaul 3 жыл бұрын
@@alexcipriani6003 right. Makes sense.
@plamentd
@plamentd 3 жыл бұрын
hm, why your for loops start from 0, 0 has been already examined
@skilz8098
@skilz8098 3 жыл бұрын
In both C & C++ arrays and their indexing are 0 based!
@plamentd
@plamentd 3 жыл бұрын
@@skilz8098 so? do you understand the code?
@skilz8098
@skilz8098 3 жыл бұрын
@@plamentd Yeah, it's not that hard to see the instructions. I'm 100% self taught in C/C++ and been at it for over 20 years. The 0 index was initialized but isn't checked for comparison until you enter the scope of the for-loop. That's why the iteration of the loops starts at 0. You still have to check the first element within the array if you want to include it within the bounds of the domain.
@plamentd
@plamentd 3 жыл бұрын
@@skilz8098 it don't need to be examined against itself
@skilz8098
@skilz8098 3 жыл бұрын
@@plamentd No, but against another elements within the array you do, I'd have to revisit the video and double check the source code again... it's a bit different seeing code in a video than writing the algorithm yourself!
@rafaelkuhn
@rafaelkuhn Жыл бұрын
Where's std::tuple and std::pair in the c++ part my man??
@user-su5sq5ib3i
@user-su5sq5ib3i 2 жыл бұрын
A
@mrcrackerist
@mrcrackerist 3 жыл бұрын
While watching this I was think that you could make a function that will return the next value on each call fist call : max value second call : min value
@dmitripogosian5084
@dmitripogosian5084 Жыл бұрын
There is always a way to make computation more wasteful
@mrcrackerist
@mrcrackerist Жыл бұрын
@@dmitripogosian5084 since i made that comment I have learned a lot more and am doing crazy stuff in C for work...
@csbnikhil
@csbnikhil 3 жыл бұрын
2 loops n times with 1 instruction is not really that different from 1 loop n times with 2 instructions.
@JacobSorber
@JacobSorber 3 жыл бұрын
Actually, depending on the architecture you're using, and the optimizations that the compiler is applying, and how big the size of the array is, these two things can be very different. Not all instructions have the same cost. You have instruction-level parallelism to consider, and these two approaches could end up with very different memory performance (cache performance and paging performance).
@sophiarodriguez1861
@sophiarodriguez1861 3 жыл бұрын
Sorry, but this is not a good explanation. To start an explanation with 23 lines code, it's by definition a poor choice.
@TomStorey96
@TomStorey96 2 жыл бұрын
If you're going to say such a thing, you should provide a better example and explanation.
@HansBezemer
@HansBezemer Жыл бұрын
When I saw this title, I considered my options. Although entertaining, I learned nothing. My tip: make a system stack. Push the stuff you want to return there. Converting pointers to integers may be a bit tricky, though. It's mostly implementation defined. Check "uintptr_t". Ok, here is a tiny implementation: #include #include intptr_t tos (intptr_t **s) {return (*((*s)-1));} void push (intptr_t **s, intptr_t v) { *(*s)++ = v;} intptr_t pop (intptr_t **s) { (*s)--; return (**s); } intptr_t depth (intptr_t **sp, intptr_t *s) { return (*sp - s); } int main (int argc, char **argv) { intptr_t stack [256]; char example [32] = "Hello world"; intptr_t *sp = stack; push (&sp, (intptr_t) example); push (&sp, 25); push (&sp, 26); printf ("tos = %ld sp = %p ", tos(&sp), sp); printf ("depth = %ld ", depth (&sp, stack)); printf ("tos = %ld sp = %p ", pop(&sp), sp); printf ("depth = %ld ", depth (&sp, stack)); printf ("tos = %ld sp = %p ", tos(&sp), sp); printf ("depth = %ld ", depth (&sp, stack)); printf ("tos = %ld sp = %p ", pop(&sp), sp); printf ("depth = %ld ", depth (&sp, stack)); printf ("example = %s ", (char *) pop(&sp)); }
Defining Constants. Should I use CONST or #DEFINE?
7:59
Jacob Sorber
Рет қаралды 55 М.
What's the Best Way to Copy a Struct in C and C++?
13:44
Jacob Sorber
Рет қаралды 33 М.
THEY WANTED TO TAKE ALL HIS GOODIES 🍫🥤🍟😂
00:17
OKUNJATA
Рет қаралды 9 МЛН
Make your Data Type more Abstract with Opaque Types in C
13:41
Jacob Sorber
Рет қаралды 48 М.
you will never ask about pointers again after watching this video
8:03
Low Level Learning
Рет қаралды 2,1 МЛН
How Senior Programmers ACTUALLY Write Code
13:37
Thriving Technologist
Рет қаралды 1,4 МЛН
Can I Handle Exceptions with Try Catch in C? (setjmp, longjmp)
11:13
When do I use a union in C or C++, instead of a struct?
11:18
Jacob Sorber
Рет қаралды 67 М.
How To Return An Array From A Function | C Programming Tutorial
13:01
Portfolio Courses
Рет қаралды 63 М.
how Google writes gorgeous C++
7:40
Low Level Learning
Рет қаралды 800 М.