How to write C functions with variable argument lists.

Поделиться
HTML-код
  • Опубликовано: 7 сен 2024

Комментарии • 117

  • @Thiagola92
    @Thiagola92 4 года назад +57

    I am surprise that this video doesn't have many views because is SUPER interesting and is not a content easy to find.
    Thank you Jacob!

    • @JacobSorber
      @JacobSorber  4 года назад +2

      Thanks. I'm glad you found it.

    • @codex8797
      @codex8797 3 года назад +1

      hey bro, I can see you are from the macaco land. That's cool, I am as well.

  • @zokalyx
    @zokalyx 3 месяца назад +2

    As I learn more and more about C I notice that it was ahead of its time.

  • @arnaudparan1419
    @arnaudparan1419 2 года назад +6

    I already knew about that topic and how to do that but watched the video anyways and I am struck with how concise, breve and clear it is, definitely great content for beginners and I wish such content would have existed when I learnt that.

  • @ravimali2814
    @ravimali2814 5 лет назад +7

    Wow, I always imagined how it worked. Today I found it. Keep up the great work.

  • @immanuelcharles2875
    @immanuelcharles2875 2 года назад +2

    I need to create a logging system and this is just what I needed! Thanks so much!

  • @thebuilderr
    @thebuilderr 6 лет назад +8

    Thanks for the tutorial Jacob! I look forward to seeing more :)

    • @JacobSorber
      @JacobSorber  6 лет назад +1

      You're welcome. Glad you enjoyed it.

  • @ArmiaKhairy
    @ArmiaKhairy 4 года назад +7

    your typing is somehow so satisfying !!

  • @idrisabdullateef1490
    @idrisabdullateef1490 2 года назад +1

    This is really amazing and straight to the point. Thank you Jacob. I'm going to try writing my own printf fuction.

  • @atulrustagi2381
    @atulrustagi2381 2 года назад +1

    I am a Cpp developer and never thought I would come across a use case where I will be needing this so never learned this.
    Today I came across a crash and have to use it and was looking for some easy and to the point tutorial, came across this one.
    Thanks for such a great video.

  • @ropersonline
    @ropersonline 4 года назад +3

    2:23: "...must also be self-promoting types, so you *can't use chars* , shorts or floats... but ints doubles or pointers are just fine."
    NB: We might want to note here that char pointers (char *) are also fine, since they count as pointers in this line-up.

  • @D_Ladybug
    @D_Ladybug 2 года назад +1

    I love you explanation, keep the energy up! could you please do a video to explain the printf code in its entirety?

  • @afraidrt
    @afraidrt 2 года назад +1

    Thank you. You really save my life !

  • @creative_tech_shorts
    @creative_tech_shorts 5 месяцев назад

    Your explanation is amazing but I expected the video to be more longer then 4 minutes I like to have good understanding with longer explanation that answers all questions about the subject.

  • @TheVertical92
    @TheVertical92 3 года назад +4

    Am i right assuming that printf counts the % placeholders in the string to know how many extra arguments were passed?

  • @anandakrishnannair
    @anandakrishnannair 3 года назад +1

    Thank you Jacob, this was the best explanation ever

  • @anthonybragato2968
    @anthonybragato2968 Год назад

    Thank you a lot JACOB

  • @nathanassefa8787
    @nathanassefa8787 Год назад

    your video is not for beginners. I always see your video, and I never understand what you teach despite compiling a great lecture in amazing way. The problem is that we beginners need detailed information to infer the concept. You are great teacher, and try to consider tyros

  • @theblackelephant
    @theblackelephant Год назад

    Mr. Jacob can you longer videos on variadic functions

  • @fargoflagrant7796
    @fargoflagrant7796 2 года назад +1

    Thank you! This was really helpful.

  • @laurisskraucis2247
    @laurisskraucis2247 5 лет назад +2

    This channel deserves more subscribers! :)

    • @JacobSorber
      @JacobSorber  5 лет назад

      Definitely. :) Glad it's helpful.

  • @ramakrishna4092
    @ramakrishna4092 2 месяца назад +1

    // While practicing functions, I encountered an error. Can you explain why?
    // I tried using `void` as an argument in the function call.
    // Why can't `void` be used this way, and what is the proper way to call a function that takes no arguments?
    void myFunction(void) {
    // Function body
    }
    int main() {
    myFunction(void); // Why is this incorrect?
    return 0;
    }

  • @Tachiguro
    @Tachiguro 2 года назад

    Thanks, you helped me a lot to understand this topic!

  • @HansBezemer
    @HansBezemer 3 года назад

    Best channel on the subject! Kudos!

  • @thingsiplay
    @thingsiplay 3 года назад +3

    When I see how variable number of arguments is done in C, I appreciate this feature in Python more. If this is builtin, it makes it so much more easy and natural to work with. Currently learning Rust here and Rust doesn't have it too as a language construct.
    If you wonder why I watch your content, even if I am not a C programmer and interested in Python and Rust only. It is because your content is so good and also why not learning a bit about C alongside. C is universal.

    • @aleksanderkrauze9304
      @aleksanderkrauze9304 2 года назад

      Rust does not have variadic functions, but it has something even more powerful. Macros. And if you really need to go that deep it has also procedural macros. Look them up.

    • @thingsiplay
      @thingsiplay 2 года назад

      @@aleksanderkrauze9304 But having variadic functions with variable number of arguments would make the code so much more cleaner. I understand now that this feature would make verifying the code at compile time extremely difficult and that is probably the reason why its not implemented. Nonetheless, it is still a feature I am missing in Rust.

    • @aleksanderkrauze9304
      @aleksanderkrauze9304 2 года назад

      @@thingsiplay There are many features, like optional arguments or functions/operators overloading, that seems nice, but result in more bloated code. Lack of them isn't a problem. It just requires different API design. It all comes down to preference, do you want to be more flexible, or have functions that you are sure you know what are doing.

    • @thingsiplay
      @thingsiplay 2 года назад

      @@aleksanderkrauze9304 Your assumption is that people who want to be flexible don't know what they are doing? I know in Python too what I am doing, when utilizing this feature. Especially when writing library functions for end user (other devs) it can be helpful to have flexible number of arguments.
      You might not miss them and be happy, but there are peoples (one of them me) are missing this feature.

    • @aleksanderkrauze9304
      @aleksanderkrauze9304 2 года назад

      @@thingsiplay I might have badly chosen my words. I apologize for that. What I meant was that usefulness of these language features comes down to programming style. It's like OOP vs. not OOP. They both can provide the same results, but both create different APIs. It's not like one of them is inherently bad, they are fine on them own. But then *can* become bloated, if wrongly used (I'm looking at you OOP). At the end of the day I believe that feeling of missing some other language feature requires a mental switch.

  • @afanoromolyricsofficial
    @afanoromolyricsofficial 2 года назад

    You inspire me! Thanks Jac.

  • @dwaynestgeorge2558
    @dwaynestgeorge2558 Год назад

    Thanks

  • @shivamsingh20
    @shivamsingh20 3 года назад

    thnx a lot sir this video cleared my doubts

  • @samuelrasquinha6712
    @samuelrasquinha6712 5 лет назад +2

    Quality Content! Thanks!

    • @JacobSorber
      @JacobSorber  5 лет назад

      You're welcome. Glad you enjoyed it.

  • @emmastro
    @emmastro 3 года назад

    Just saved my day! Thanks a lot for the tutorial!

  • @fxvlad
    @fxvlad 4 года назад +3

    Jacob, pls tell the music's name. I found it very suitable as a background for programming

    • @mustafaaljanabi4818
      @mustafaaljanabi4818 3 года назад +1

      If im not mistaken. I think he used this video: ruclips.net/video/1ZYbU82GVz4/видео.html

    • @fxvlad
      @fxvlad 3 года назад

      @@mustafaaljanabi4818 thank you mate!

    • @mustafaaljanabi4818
      @mustafaaljanabi4818 3 года назад

      @@fxvlad no worries brother.

  • @abd_el_ouahab3824
    @abd_el_ouahab3824 3 года назад

    your idea was clear & good thankssss .
    add (int num, ...) is there a way to predict num you know to make dynamically like what we do in varargs of java ?

  • @aminemarzouki794
    @aminemarzouki794 6 лет назад +1

    Nice tutorial professor. Would please explain this concept more in depth ? I'm having issues to understand why that works, because in the loop part, how do we know which argument do va_arg() returns ? There is no index in the body of the loop, to control that. So May I suppose, that for each call of the va_arg(), the index of the arguments increases ? Let's say for example, I want to create a min variadic function, that returns the minimum value from the list of arguments, how can I skip the first, take the second and then treat the rest ?

    • @JacobSorber
      @JacobSorber  6 лет назад +5

      Yes, the "args" variable is basically a pointer to the place on the stack where the arguments are stored. Each call to va_arg, updates that pointer to point to the next argument. So, you are working strictly sequentially through the argument list. So, to skip an argument you still need to read it, using va_arg, but you just write your program so it ignores it. Also, you might want to look at how va_arg is implemented. It might make things a bit clearer. (www.rpi.edu/dept/cis/software/g77-mingw32/include/stdarg.h).

    • @aminemarzouki794
      @aminemarzouki794 6 лет назад

      Thank you sir. Now it's more clear. +1sub :)

    • @unperrier5998
      @unperrier5998 2 года назад

      @@aminemarzouki794 it's a little more complicated than just being a pointer on to the stack: it depends on the ABI for a given architecture, which in particular describes how arguments are passed to functions for that architecture.
      For example on amd64 (the name for all 64 bits Intel and amd), the compiler will place the first few arguments in registers and the rest on the stack.
      So that va_arg variable also knows that the first few arguments need to be taken from registers, and so it does use registers, until all registers have been exhausted and then it will switch to getting the following arguments from the stack. The va_args has specific fields to track this.

  • @thendoabbey9966
    @thendoabbey9966 6 лет назад +2

    thanks for the video,am currently doing a project where i have to recode the function printf,i must manage %%,conversions: sSpdDioOuUxXcC,the flags #0-+ and space, and precision,where do i go about that

    • @JacobSorber
      @JacobSorber  6 лет назад +3

      That's a pretty broad question. You need to make a variadic function, like those described in the video. Then you need code that will go through the format string and identify all of the variable insertions, then grab them as you find them (as shown in the video).

  • @may8049
    @may8049 3 года назад

    legend

  • @arioamin
    @arioamin 4 года назад +1

    How would variadic function pointer syntax look like? Maybe an example use

    • @JacobSorber
      @JacobSorber  4 года назад

      Do you mean, how would you pass a pointer, instead of an int? It's really the same. It look something like this "int *vptr = va_arg(args, int *);"

    • @arioamin
      @arioamin 4 года назад

      @@JacobSorber No I meant if I have a typedefined function pointer such as ' typedef void (*fp) (); ' as you see this function pointer will not pass any arguments to the function it later will point to, but it can be used to point to a function of type void without any arguments,
      If I want to set up variable argument amount to pass through that pointer how would it be done while also allowing to point to functions without in-arguments?
      I want to be able to access and call many void functions using the function pointer type shown above, not only functions without arguments
      if I use typedef void (*fp) (void*, ... ); it won't work to point to argument-less functions

    • @JacobSorber
      @JacobSorber  4 года назад

      ​@@arioamin Ah, I see. I think you're running up against the limitations of the language. Variadic functions in C require at least one argument because they have no built-in way to know how many arguments were passed in otherwise. I suppose you could use typecasts, but that's probably going to get messy. Sorry I don't have a happier answer. There might be some way I'm not aware of.

    • @arioamin
      @arioamin 4 года назад

      @@JacobSorber Maybe for the time being the simplest way is to use two different function pointers, one for calling functions without any arguments and one for functions with arguments. Why I am doing this is because I am making a command structure with commands having member like command-format, command-name, command-info function pointer

  • @sofiane1o1
    @sofiane1o1 3 года назад +1

    Yo, Jacob just found out your channel while searching for this exact tutorial. I got a question : my school require me to recreate the printf function from scratch. My issue is that the prototype I must use for the function is the following : int ft_printf(const char *input, ...). But you said that to use va_starts it was required that the argument before the ellipse was the number of variable arguments so not a char * as I was given. I was thinking about making a function that would parse the string and count the arguments printf would require and then use that as "num". Do you have any general advice to proceed about that since it's a pretty big project ?
    Cheers, love your videos I am learning a lot.

    • @JacobSorber
      @JacobSorber  3 года назад +1

      The first argument doesn't need to be a number, but it does need to tell you what the remaining arguments are. In the case of printf, the format string (a char*) describes what arguments it will expect to find. For example, ft_printf("%s %d %d",...) tells me that I'm going to have a char* and two ints. Best of luck.

    • @JaccovanSchaik
      @JaccovanSchaik 3 года назад +2

      @@JacobSorber It doesn't even have to tell you that. There has to *be* at least one fixed argument, but you could just as easily use a special "marker" value as the last argument to let the called function know there won't be any more. You could have a function that takes a variable number of pointers with the last pointer being NULL, for example. In that case the first argument doesn't need to specify the number of arguments to follow.

    • @edwardmacnab354
      @edwardmacnab354 2 года назад +1

      How to create the printf function from scratch : look at the source code for printf !

  • @arioriabdulrafiu8773
    @arioriabdulrafiu8773 10 месяцев назад

    I got a question that you cannot answer...
    I actually don't really understand this.
    The va_start(a, b). Those the function start from a to b, or b to a.

  • @somedude5414
    @somedude5414 4 года назад

    Sweet!

  • @rafalzasada8826
    @rafalzasada8826 4 года назад +1

    What exactly is self-promoting type in C?

    • @JacobSorber
      @JacobSorber  4 года назад +3

      Let me know if this helps.
      www.geeksforgeeks.org/integer-promotions-in-c/

  • @baberaham
    @baberaham 5 лет назад

    I was looking up videos because upon learning about the va list, I was under the impression that you can execute your program along with the arguments by entering something like "./a.out 3 7 8 9", 3 representing the number of arguments hence is followed by 7 8 9. Is this possible or did I just misunderstand va lists completely?

    • @JacobSorber
      @JacobSorber  4 года назад +2

      I'm not 100% sure I understand the question, but I'll try. When you're running a program from the command-line ("./a.out 1 2 3 4") you can pass arguments ("1 2 3 4", in this case), but you don't have to pass in the number of arguments explicitly. Ths system will do that automatically, and pass it to main, as the argc variable. This video is, instead, focused on writing functions that are called within your programs where the number of arguments will vary.

  • @vinhtruonghuynh7968
    @vinhtruonghuynh7968 5 лет назад

    hi Prof,
    in the example of print_ints() function, for the va_start(), we must specify the number of optional arguments in the required argument "num" which is an integer.
    But in the example of printf() function, for the va_start() , i do not understand why we do not need to specify the length of the string pointed to by required argument "format".
    in the first example of print_ints(), if we do not give the correct number of optional arguments, it would result in missing or incorrect output. But in the printf(), we do not need to pass the number of the optional arguments into the function but rather just a string. Could you help explaining my concern ?

    • @JacobSorber
      @JacobSorber  5 лет назад +1

      The format string tells you how many arguments to expect. For example a format string like this ("%d, %d, %s
      ") will expect three arguments.

    • @vinhtruonghuynh7968
      @vinhtruonghuynh7968 5 лет назад

      @@JacobSorber i think there is a misunderstanding in my question
      In the first example for printing the integer, we have to pass the number of variable arguments indicated by "int num" to the print_ints(). The variable "num" is then passed to va_start() to specify the number of variable arguments indicated by "..." of print_ints( int num, ... ).
      In case we use less than the given "num" -> print_ints(2,1); -> Output: 1 (The unused argument is missing)
      In case we use more than the given "num" -> print_ints(2,1,3,4); -> Output: 431235 (Undefined behavior)
      => The last required argument "num" must always define the number of variable arguments.
      But in the second example for printing a string, we are just passing a string indicated by "char* format" to the printf().
      For example:
      int first_number = 1;
      int second_number = 2;
      printf("This is just a string not a number. First number: %d, Second number: %d
      ", first_number, second_number);
      -> Output: This is just a string not a number. First number: 1, Second number: 2
      The string "This is just a string not a number. First number: %d, Second number: %d
      " is not a number. How can it help the function printf() to identify that there are 2 variable arguments (first_number and second_number) passed to the function ?
      I mean here "num" is an integer and it can be used as the number of variable arguments. But "format" is a string, not a number, then what would help printf() to identify its number of variable arguments ?

    • @JacobSorber
      @JacobSorber  5 лет назад +3

      @@vinhtruonghuynh7968 Ah, I see. The argument passed to va_start just tells it where the variable arguments start (after "num" or after "format" in my examples). It's up to your code to interpret those arguments. So, in the printf example, the format string is analyzed in vfprintf to figure out how many arguments there should be.

    • @vinhtruonghuynh7968
      @vinhtruonghuynh7968 5 лет назад

      @@JacobSorber Thank you sir,
      it is really helpful.

  • @eom-dev
    @eom-dev 3 года назад

    I was under the impression that one could not pass a raw data type to a function, but va_arg takes int as a parameter - what is going on there?

    • @beni5154
      @beni5154 3 года назад +3

      va_arg is a macro, not a function

  • @worldshaper1723
    @worldshaper1723 3 года назад

    How does Neuralink and C work together?

  • @MultiNova100
    @MultiNova100 6 лет назад +1

    What's self promoting types?

    • @JacobSorber
      @JacobSorber  6 лет назад +1

      There's a very good explanation of type promotion in C here: stackoverflow.com/questions/46073295/implicit-type-promotion-rules

    • @unperrier5998
      @unperrier5998 2 года назад

      @@JacobSorber that's a great link, my head hurts :)
      Thanks for sharing.
      And I agree with him: most average C programers won't know why casting works, they just do.
      No way I will remember all this theory on type promotion, especially when I just need to use "signed int" all the way o avoid problems (mostly :) )

  • @Dtvangogh
    @Dtvangogh 4 года назад

    what vs code theme is that?

  • @MultiNova100
    @MultiNova100 6 лет назад

    How does vfprintf know how long the arg list is?

    • @JacobSorber
      @JacobSorber  6 лет назад +5

      The format string tells vfprintf how many arguments should be there. Printf is so common that some c compilers also statically check to make sure that the number of args matches the number specified in the format string. But, as I showed in the example, there isn't any enforcement mechanism to ensure you don't try to provide too many args or too few.

  • @incyberideas
    @incyberideas 4 года назад

    Jacob, if some one not native in english it more difficult to listen with music in background.

  • @clairevicidomini3199
    @clairevicidomini3199 6 лет назад

    Hello, i would like to ask a question that ,strangely enough ,nobody seems to ask on internet.
    How in the good lord's name does va_arg literally requires a *type* as an argument?!?
    Is it something that i can reproduce in my own functions?
    Also, how can vfprintf know how many arguments have been passed?
    It would be really useful, thanks ^-^.

    • @JacobSorber
      @JacobSorber  6 лет назад

      Good question. C isn't very introspective. You can't pass a type to a function, for example, but va_arg isn't a function. It's a preprocessor macro. So, it's not doing any type checking on its arguments. It's just moving text around. And, yes you can do this in your own code.

  • @sanusihassan7125
    @sanusihassan7125 6 лет назад

    :s What is the meaning of va_list,arg start And what are they doing

    • @JacobSorber
      @JacobSorber  6 лет назад +5

      "va" means "variable arguments". va_list - a data structure that keeps track of where you are on the call stack as you pull off those arguments. va_start initializes the va_list structure (it tells it where to start pulling arguments-in printf, it's after format). va_arg just gets the next argument. You have to tell it what type the argument is so it knows what size it is. va_end just says, we're done pulling off variable arguments. On the compilers that I use, va_end really doesn't do anything.

  • @user-hg5ss9vm6v
    @user-hg5ss9vm6v 3 года назад

    Школа 21!

  • @jonagostini8782
    @jonagostini8782 3 года назад

    1000th like... Did I win a prize?

  • @aatifghani3014
    @aatifghani3014 2 года назад

    But it is super fast. And still little tough to understand

  • @fabouwes9240
    @fabouwes9240 2 года назад

    Didn't understand

  • @RAMB0VI
    @RAMB0VI 4 года назад

    Matthew McConaughey of Coding.

  • @aishwaryashutosh7763
    @aishwaryashutosh7763 4 года назад

    I am feeling stupid

  • @chevalierdeloccident5949
    @chevalierdeloccident5949 6 лет назад

    The routine `stdarg` is a terrible implementation of a variadic function. It is too convoluted to type down and too rudimentary in scope. What if I wanted to create a function that, for example, prints the name, age, and height of an arbitrary number of people (along with other attributes of these people). I would need to pass multiple variadic arguments to that function. I know of only one programing language that implements this perfectly well. Sadly, the Wolfram Language™ is proprietary.

    • @JacobSorber
      @JacobSorber  6 лет назад +1

      I agree with the general comment about stdarg. It leaves much to be desired, as does C's type system. But, from your specific example (the name, age, height printer), I'm not sure exactly what you're looking for. Based on the explanation, this sounds like something C could do (along with most other languages).

    • @chevalierdeloccident5949
      @chevalierdeloccident5949 6 лет назад

      For example a `void record_print(vararg1, vararg2, vararg3, ...)` where I can `record_print({"Erik", "Lisa", "Tom", ...}, {"Young", "Old", "Mid-age",...}, {"Boy", "Lady", "Man"...}, {...})`. I don't see how this is possible with `stdarg`. Is very distressing to find a way to define this type of "polyvariadic" function in nearly all languages.

    • @chevalierdeloccident5949
      @chevalierdeloccident5949 6 лет назад

      By the way, is that a package you have installed on Atom for invoking the compiler through a command line? If "yes", which one is it? Looks pretty! :)

    • @JacobSorber
      @JacobSorber  6 лет назад +1

      Yes, stdarg would have a hard time doing this. I'm not sure that style of variadic function is a good idea (from a software engineering perspective), but you're right, most languages don't support this without painful contortion.

    • @JacobSorber
      @JacobSorber  6 лет назад +1

      Yeah, it's very convenient: "platformio-ide-terminal".

  • @simonfiers1681
    @simonfiers1681 4 года назад

    Thank you for the great content. The background music however has no added value tbh.

  • @nazaraljendli9758
    @nazaraljendli9758 2 года назад

    a new concept video of only 4 minutes and half of them were story time. when you make a video like this put your self in our position and watch your video as if you didnt know the topic then you can understand how bad the video was

    • @JacobSorber
      @JacobSorber  2 года назад

      Half? There are only 30s of story time (1/8th), and I include it in an effort to give you a motivating example for why someone might actually want to create a variadic function. Sorry the format wasn't helpful, but seriously, it will help me put myself into your position if you provide constructive suggestions, rather than just saying that the video was "bad".