Why is C/C++ main argv declared as “char* argv[]” rather than just “char* argv”?












17















Why is argv declared as "a pointer to pointer to the first index of the array", rather than just being "a pointer to the first index of array" (char* argv)?



Why is the notion of "pointer to pointer" required here?










share|improve this question









New contributor




a user is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
















  • 3





    "a pointer to pointer to the first index of the array" - That's not a correct description of char* argv or char**. That's a pointer to a pointer to a character; specifically the outer pointer points to the first pointer in an array, and the inner pointers point to the first characters of nul-terminated strings. There's no indices involved here.

    – Sebastian Redl
    yesterday








  • 6





    How would you get the second argument if it was just char* argv?

    – gnasher729
    yesterday






  • 11





    Your life will get easier when you put the space in the right place. char* argv puts the space in the wrong place. Say char *argv, and now it is clear that this means "the expression *argv[n] is a variable of type char". Don't get caught up in trying to work out what's a pointer and what's a pointer to a pointer, and so on. The declaration is telling you what operations you can perform on this thing.

    – Eric Lippert
    21 hours ago













  • It's NOT. It's declared as "char **argv", not "char *argv". That is, a pointer to a list of pointers to char., not a simple pointer to a string of char. Each individual argument coul be in non-contiguous memory locations.

    – jamesqf
    20 hours ago






  • 1





    Mentally compare char * argv to the similar C++ construct std::string argv, and it might be easier to parse. ...Just don't start actually writing it that way!

    – Justin Time
    18 hours ago
















17















Why is argv declared as "a pointer to pointer to the first index of the array", rather than just being "a pointer to the first index of array" (char* argv)?



Why is the notion of "pointer to pointer" required here?










share|improve this question









New contributor




a user is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
















  • 3





    "a pointer to pointer to the first index of the array" - That's not a correct description of char* argv or char**. That's a pointer to a pointer to a character; specifically the outer pointer points to the first pointer in an array, and the inner pointers point to the first characters of nul-terminated strings. There's no indices involved here.

    – Sebastian Redl
    yesterday








  • 6





    How would you get the second argument if it was just char* argv?

    – gnasher729
    yesterday






  • 11





    Your life will get easier when you put the space in the right place. char* argv puts the space in the wrong place. Say char *argv, and now it is clear that this means "the expression *argv[n] is a variable of type char". Don't get caught up in trying to work out what's a pointer and what's a pointer to a pointer, and so on. The declaration is telling you what operations you can perform on this thing.

    – Eric Lippert
    21 hours ago













  • It's NOT. It's declared as "char **argv", not "char *argv". That is, a pointer to a list of pointers to char., not a simple pointer to a string of char. Each individual argument coul be in non-contiguous memory locations.

    – jamesqf
    20 hours ago






  • 1





    Mentally compare char * argv to the similar C++ construct std::string argv, and it might be easier to parse. ...Just don't start actually writing it that way!

    – Justin Time
    18 hours ago














17












17








17


4






Why is argv declared as "a pointer to pointer to the first index of the array", rather than just being "a pointer to the first index of array" (char* argv)?



Why is the notion of "pointer to pointer" required here?










share|improve this question









New contributor




a user is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.












Why is argv declared as "a pointer to pointer to the first index of the array", rather than just being "a pointer to the first index of array" (char* argv)?



Why is the notion of "pointer to pointer" required here?







c++ c






share|improve this question









New contributor




a user is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











share|improve this question









New contributor




a user is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









share|improve this question




share|improve this question








edited 3 hours ago









Peter Mortensen

1,11521114




1,11521114






New contributor




a user is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









asked yesterday









a usera user

9514




9514




New contributor




a user is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.





New contributor





a user is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






a user is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.








  • 3





    "a pointer to pointer to the first index of the array" - That's not a correct description of char* argv or char**. That's a pointer to a pointer to a character; specifically the outer pointer points to the first pointer in an array, and the inner pointers point to the first characters of nul-terminated strings. There's no indices involved here.

    – Sebastian Redl
    yesterday








  • 6





    How would you get the second argument if it was just char* argv?

    – gnasher729
    yesterday






  • 11





    Your life will get easier when you put the space in the right place. char* argv puts the space in the wrong place. Say char *argv, and now it is clear that this means "the expression *argv[n] is a variable of type char". Don't get caught up in trying to work out what's a pointer and what's a pointer to a pointer, and so on. The declaration is telling you what operations you can perform on this thing.

    – Eric Lippert
    21 hours ago













  • It's NOT. It's declared as "char **argv", not "char *argv". That is, a pointer to a list of pointers to char., not a simple pointer to a string of char. Each individual argument coul be in non-contiguous memory locations.

    – jamesqf
    20 hours ago






  • 1





    Mentally compare char * argv to the similar C++ construct std::string argv, and it might be easier to parse. ...Just don't start actually writing it that way!

    – Justin Time
    18 hours ago














  • 3





    "a pointer to pointer to the first index of the array" - That's not a correct description of char* argv or char**. That's a pointer to a pointer to a character; specifically the outer pointer points to the first pointer in an array, and the inner pointers point to the first characters of nul-terminated strings. There's no indices involved here.

    – Sebastian Redl
    yesterday








  • 6





    How would you get the second argument if it was just char* argv?

    – gnasher729
    yesterday






  • 11





    Your life will get easier when you put the space in the right place. char* argv puts the space in the wrong place. Say char *argv, and now it is clear that this means "the expression *argv[n] is a variable of type char". Don't get caught up in trying to work out what's a pointer and what's a pointer to a pointer, and so on. The declaration is telling you what operations you can perform on this thing.

    – Eric Lippert
    21 hours ago













  • It's NOT. It's declared as "char **argv", not "char *argv". That is, a pointer to a list of pointers to char., not a simple pointer to a string of char. Each individual argument coul be in non-contiguous memory locations.

    – jamesqf
    20 hours ago






  • 1





    Mentally compare char * argv to the similar C++ construct std::string argv, and it might be easier to parse. ...Just don't start actually writing it that way!

    – Justin Time
    18 hours ago








3




3





"a pointer to pointer to the first index of the array" - That's not a correct description of char* argv or char**. That's a pointer to a pointer to a character; specifically the outer pointer points to the first pointer in an array, and the inner pointers point to the first characters of nul-terminated strings. There's no indices involved here.

– Sebastian Redl
yesterday







"a pointer to pointer to the first index of the array" - That's not a correct description of char* argv or char**. That's a pointer to a pointer to a character; specifically the outer pointer points to the first pointer in an array, and the inner pointers point to the first characters of nul-terminated strings. There's no indices involved here.

– Sebastian Redl
yesterday






6




6





How would you get the second argument if it was just char* argv?

– gnasher729
yesterday





How would you get the second argument if it was just char* argv?

– gnasher729
yesterday




11




11





Your life will get easier when you put the space in the right place. char* argv puts the space in the wrong place. Say char *argv, and now it is clear that this means "the expression *argv[n] is a variable of type char". Don't get caught up in trying to work out what's a pointer and what's a pointer to a pointer, and so on. The declaration is telling you what operations you can perform on this thing.

– Eric Lippert
21 hours ago







Your life will get easier when you put the space in the right place. char* argv puts the space in the wrong place. Say char *argv, and now it is clear that this means "the expression *argv[n] is a variable of type char". Don't get caught up in trying to work out what's a pointer and what's a pointer to a pointer, and so on. The declaration is telling you what operations you can perform on this thing.

– Eric Lippert
21 hours ago















It's NOT. It's declared as "char **argv", not "char *argv". That is, a pointer to a list of pointers to char., not a simple pointer to a string of char. Each individual argument coul be in non-contiguous memory locations.

– jamesqf
20 hours ago





It's NOT. It's declared as "char **argv", not "char *argv". That is, a pointer to a list of pointers to char., not a simple pointer to a string of char. Each individual argument coul be in non-contiguous memory locations.

– jamesqf
20 hours ago




1




1





Mentally compare char * argv to the similar C++ construct std::string argv, and it might be easier to parse. ...Just don't start actually writing it that way!

– Justin Time
18 hours ago





Mentally compare char * argv to the similar C++ construct std::string argv, and it might be easier to parse. ...Just don't start actually writing it that way!

– Justin Time
18 hours ago










6 Answers
6






active

oldest

votes


















47














Argv is basically like this:



enter image description here



So on the left is the argument itself--what's actually passed as a parameter to main. That contains the address of an array of pointers. Each of those points to some place in memory containing the text of the corresponding argument that was passed on the command line. Then, at the end of that array there's guaranteed to be a null pointer.



Note that the actual storage for the individual arguments are at least potentially allocated separately from each other, so their addresses in memory might be arranged fairly randomly (but depending on how things happen to be written, they could also be in a single contiguous block of memory--you simply don't know or and shouldn't care).






share|improve this answer



















  • 40





    Whatever layout engine drew that diagram for you has a bug in their minimize-crossings algorithm!

    – Eric Lippert
    21 hours ago






  • 29





    @EricLippert Could be intentional to emphasize that that the pointees might not be contiguous nor in order.

    – jamesdlin
    17 hours ago






  • 1





    I would say it's intentional

    – Michael
    16 hours ago






  • 17





    It was certainly intentional--and I'd guess Eric probably figured that, but (correctly, IMO) thought the comment was funny anyway.

    – Jerry Coffin
    11 hours ago






  • 1





    @JerryCoffin, one might also point out that even if the actual arguments were contiguous in memory, they can have arbitrary lengths, so one would still need distinct pointers for each of them to be able to access argv[i] without scanning through all the previous ones.

    – ilkkachu
    3 hours ago



















15














Because that's what the operating system provides :-)



Your question is a little bit of a chicken/egg inversion issue. The problem is not to choose what you want in C++, the problem is how you say in C++ what the OS is giving you.



Unix passes an array of "strings", each string being a command argument. In C/C++, a string is a "char*", so an array of strings is char* argv, or char** argv, according to taste.






share|improve this answer








New contributor




passer-by is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
















  • 8





    No, it's exactly "the problem to choose what you want in C++". Windows, for example, provides the command line as a single string, and yet C/C++ programs still receive their argv array — the runtime takes care of tokenizing the command line and building the argv array at the startup.

    – Joker_vD
    yesterday






  • 9





    @Joker_vD I think in a twisted way it is about what the OS gives you. Specifically: I guess C++ did it this way because C did it this way, and C did it this way because at the time C and Unix were so inextricably linked and Unix did it this way.

    – Daniel Wagner
    23 hours ago






  • 1





    @DanielWagner: Yes, this is from C's Unix heritage. On Unix / Linux a minimal _start that calls main just needs to pass main a pointer to the existing argv array in memory; it's already in the right format. The kernel copies it from the argv argument to the execve(const char *filename, char *const argv, char *const envp) system call that was made to start a new executable. (On Linux, argv (the array itself) and argc are on the stack on process entry. I assume most Unixes are the same, because that's a good place for it.)

    – Peter Cordes
    18 hours ago








  • 5





    But Joker's point here is that the C / C++ standards leave it up to the implementation where the args come from; they don't have to be straight from the OS. On an OS that passes a flat string, a good C++ implementation should include tokenizing, instead of setting argc=2 and passing the whole flat string. (Following the letter of the standard is not sufficient to be useful; it intentionally leaves a lot of room for implementation choices.) Although some Windows programs will want to treat quotes specially, so real implementations do provide a way to get the flat string, too.

    – Peter Cordes
    18 hours ago






  • 1





    Basile's answer is pretty much this + @Joker's correction and my comments, with more details.

    – Peter Cordes
    17 hours ago



















11














First, as a parameter declaration, char **argv is the same as char *argv; they both imply a pointer to (an array or set of one or more possible) pointer(s) to strings.



Next, if you only have "pointer to char" (e.g. just char *, then in order to access the nth item, you'll have to scan the first n-1 items to find the nth item's start.  (And this would also impose the requirement that each of the strings are stored contiguously.)



With the array of pointers, you can directly index the nth item — so (while not strictly necessary — assuming the strings are contiguous) it is generally much more convenient.



To illustrate:



./program hello world



argc = 3
argv[0] --> "./program"
argv[1] --> "hello"
argv[2] --> "world"


It is possible that, in an os provided array of characters:



            "./programhelloworld"
argv[0] ^
argv[1] ^
argv[2] ^


if argv were just a "pointer to char" you might see



       "./programhelloworld"
argv ^


However (though likely by design of the os) there is no real guarantee that the three strings "./program", "hello", and "world" are contiguous.  Further, this kind of "single pointer to multiple contiguous strings" is a more unusual data type construct (for C), especially compared with array of pointers to string.






share|improve this answer


























  • what if instead of , argv --> "helloworld" you have argv --> index 0 of the array (hello), just like a normal array. why isn't this doable? then you keep reading the array argc times. then you pass argv itself and not a pointer to argv.

    – a user
    yesterday













  • @auser, that's what argv --> "./programhelloworld" is: a pointer to the first char (i.e. the ".") If you take that pointer past the first , then you have a pointer to "hello", and after that to "world". After argc times (hitting "), you're done. Sure, it can be made to work, and as I said, an unusual construct.

    – Erik Eidt
    yesterday











  • You forgot to state that in your example argv[4] is NULL

    – Basile Starynkevitch
    yesterday











  • @BasileStarynkevitch, oh, ok!

    – Erik Eidt
    yesterday






  • 2





    There is a guarantee that (at least initially) argv[argc] == NULL. In this case that's argv[3], not argv[4].

    – Miral
    8 hours ago



















10















Why C/C++ main argv is declared as “char* argv”




A possible answer is because the C11 standard n1570 (in §5.1.2.2.1 Program startup) and the C++11 standard n3337 (in §3.6.1 main function) require that for hosted environments (but notice that the C standard mentions also §5.1.2.1 freestanding environments) See also this.



The next question is why did the C and C++ standards choose main to have such a int main(int argc, char**argv) signature? The explanation is largely historical: C was invented with Unix, which has a shell which does globbing before doing fork (which is a system call to create a process) and execve (which is the system call to execute a program), and that execve transmits an array of string program arguments and is related to the main of the executed program. Read more about the Unix philosophy and about ABIs.



And C++ tried hard to follow the conventions of C and be compatible with it. It could not define main to be incompatible with C traditions.



If you designed an operating system from scratch (still having a command line interface) and a programming language for it from scratch, you'll be free to invent different program starting conventions. And other programming languages (e.g. Common Lisp or Ocaml or Go) have different program starting conventions.



In practice, main is invoked by some crt0 code. Notice that on Windows the globbing may be done by each program in the equivalent of crt0, and some Windows programs can start thru the non-standard WinMain entry point. On Unix, globbing is done by the shell (and crt0 is adapting the ABI, and the initial call stack layout that it has specified, to calling conventions of your C implementation).






share|improve this answer

































    9














    Rather than thinking of it as "pointer to pointer", it helps to think of it as "array of strings", with denoting array and char* denoting string. When you run a program, you can pass it one or more command-line arguments and these are reflected in the arguments to main: argc is the count of arguments and argv lets you access individual arguments.






    share|improve this answer



















    • 2





      +1 This! In many languages - bash, PHP, C, C++ - argv is an array of strings. Of this you have to think when you see char ** or char *, which is the same.

      – rexkogitans
      23 hours ago



















    1














    In many cases the answer is "because it's a standard". To quote C99 standard:




    — If the value of argc is greater than zero, the array members argv[0] through
    argv[argc-1] inclusive shall contain pointers to strings, which are given
    implementation-defined values by the host environment prior to program startup.




    Of course, before it has been standardized it was already in use by K&R C in early Unix implementations, with the purpose of storing command-line parameters (something you have to care in Unix shell such as /bin/bash or /bin/sh but not in embedded systems). To quote first edition of K&R's "The C Programming Language" (pg. 110):




    The first (conventionally called argc) is the number of command-line arguments the program was invoked with; the second (argv) is a pointer to an array of character strings that contain the arguments, one per string.







    share|improve this answer










    New contributor




    Sergiy Kolodyazhnyy is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.




















      Your Answer








      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "131"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: false,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: null,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: false,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });






      a user is a new contributor. Be nice, and check out our Code of Conduct.










      draft saved

      draft discarded


















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsoftwareengineering.stackexchange.com%2fquestions%2f385819%2fwhy-is-c-c-main-argv-declared-as-char-argv-rather-than-just-char-argv%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown




















      StackExchange.ready(function () {
      $("#show-editor-button input, #show-editor-button button").click(function () {
      var showEditor = function() {
      $("#show-editor-button").hide();
      $("#post-form").removeClass("dno");
      StackExchange.editor.finallyInit();
      };

      var useFancy = $(this).data('confirm-use-fancy');
      if(useFancy == 'True') {
      var popupTitle = $(this).data('confirm-fancy-title');
      var popupBody = $(this).data('confirm-fancy-body');
      var popupAccept = $(this).data('confirm-fancy-accept-button');

      $(this).loadPopup({
      url: '/post/self-answer-popup',
      loaded: function(popup) {
      var pTitle = $(popup).find('h2');
      var pBody = $(popup).find('.popup-body');
      var pSubmit = $(popup).find('.popup-submit');

      pTitle.text(popupTitle);
      pBody.html(popupBody);
      pSubmit.val(popupAccept).click(showEditor);
      }
      })
      } else{
      var confirmText = $(this).data('confirm-text');
      if (confirmText ? confirm(confirmText) : true) {
      showEditor();
      }
      }
      });
      });






      6 Answers
      6






      active

      oldest

      votes








      6 Answers
      6






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      47














      Argv is basically like this:



      enter image description here



      So on the left is the argument itself--what's actually passed as a parameter to main. That contains the address of an array of pointers. Each of those points to some place in memory containing the text of the corresponding argument that was passed on the command line. Then, at the end of that array there's guaranteed to be a null pointer.



      Note that the actual storage for the individual arguments are at least potentially allocated separately from each other, so their addresses in memory might be arranged fairly randomly (but depending on how things happen to be written, they could also be in a single contiguous block of memory--you simply don't know or and shouldn't care).






      share|improve this answer



















      • 40





        Whatever layout engine drew that diagram for you has a bug in their minimize-crossings algorithm!

        – Eric Lippert
        21 hours ago






      • 29





        @EricLippert Could be intentional to emphasize that that the pointees might not be contiguous nor in order.

        – jamesdlin
        17 hours ago






      • 1





        I would say it's intentional

        – Michael
        16 hours ago






      • 17





        It was certainly intentional--and I'd guess Eric probably figured that, but (correctly, IMO) thought the comment was funny anyway.

        – Jerry Coffin
        11 hours ago






      • 1





        @JerryCoffin, one might also point out that even if the actual arguments were contiguous in memory, they can have arbitrary lengths, so one would still need distinct pointers for each of them to be able to access argv[i] without scanning through all the previous ones.

        – ilkkachu
        3 hours ago
















      47














      Argv is basically like this:



      enter image description here



      So on the left is the argument itself--what's actually passed as a parameter to main. That contains the address of an array of pointers. Each of those points to some place in memory containing the text of the corresponding argument that was passed on the command line. Then, at the end of that array there's guaranteed to be a null pointer.



      Note that the actual storage for the individual arguments are at least potentially allocated separately from each other, so their addresses in memory might be arranged fairly randomly (but depending on how things happen to be written, they could also be in a single contiguous block of memory--you simply don't know or and shouldn't care).






      share|improve this answer



















      • 40





        Whatever layout engine drew that diagram for you has a bug in their minimize-crossings algorithm!

        – Eric Lippert
        21 hours ago






      • 29





        @EricLippert Could be intentional to emphasize that that the pointees might not be contiguous nor in order.

        – jamesdlin
        17 hours ago






      • 1





        I would say it's intentional

        – Michael
        16 hours ago






      • 17





        It was certainly intentional--and I'd guess Eric probably figured that, but (correctly, IMO) thought the comment was funny anyway.

        – Jerry Coffin
        11 hours ago






      • 1





        @JerryCoffin, one might also point out that even if the actual arguments were contiguous in memory, they can have arbitrary lengths, so one would still need distinct pointers for each of them to be able to access argv[i] without scanning through all the previous ones.

        – ilkkachu
        3 hours ago














      47












      47








      47







      Argv is basically like this:



      enter image description here



      So on the left is the argument itself--what's actually passed as a parameter to main. That contains the address of an array of pointers. Each of those points to some place in memory containing the text of the corresponding argument that was passed on the command line. Then, at the end of that array there's guaranteed to be a null pointer.



      Note that the actual storage for the individual arguments are at least potentially allocated separately from each other, so their addresses in memory might be arranged fairly randomly (but depending on how things happen to be written, they could also be in a single contiguous block of memory--you simply don't know or and shouldn't care).






      share|improve this answer













      Argv is basically like this:



      enter image description here



      So on the left is the argument itself--what's actually passed as a parameter to main. That contains the address of an array of pointers. Each of those points to some place in memory containing the text of the corresponding argument that was passed on the command line. Then, at the end of that array there's guaranteed to be a null pointer.



      Note that the actual storage for the individual arguments are at least potentially allocated separately from each other, so their addresses in memory might be arranged fairly randomly (but depending on how things happen to be written, they could also be in a single contiguous block of memory--you simply don't know or and shouldn't care).







      share|improve this answer












      share|improve this answer



      share|improve this answer










      answered yesterday









      Jerry CoffinJerry Coffin

      40.5k575149




      40.5k575149








      • 40





        Whatever layout engine drew that diagram for you has a bug in their minimize-crossings algorithm!

        – Eric Lippert
        21 hours ago






      • 29





        @EricLippert Could be intentional to emphasize that that the pointees might not be contiguous nor in order.

        – jamesdlin
        17 hours ago






      • 1





        I would say it's intentional

        – Michael
        16 hours ago






      • 17





        It was certainly intentional--and I'd guess Eric probably figured that, but (correctly, IMO) thought the comment was funny anyway.

        – Jerry Coffin
        11 hours ago






      • 1





        @JerryCoffin, one might also point out that even if the actual arguments were contiguous in memory, they can have arbitrary lengths, so one would still need distinct pointers for each of them to be able to access argv[i] without scanning through all the previous ones.

        – ilkkachu
        3 hours ago














      • 40





        Whatever layout engine drew that diagram for you has a bug in their minimize-crossings algorithm!

        – Eric Lippert
        21 hours ago






      • 29





        @EricLippert Could be intentional to emphasize that that the pointees might not be contiguous nor in order.

        – jamesdlin
        17 hours ago






      • 1





        I would say it's intentional

        – Michael
        16 hours ago






      • 17





        It was certainly intentional--and I'd guess Eric probably figured that, but (correctly, IMO) thought the comment was funny anyway.

        – Jerry Coffin
        11 hours ago






      • 1





        @JerryCoffin, one might also point out that even if the actual arguments were contiguous in memory, they can have arbitrary lengths, so one would still need distinct pointers for each of them to be able to access argv[i] without scanning through all the previous ones.

        – ilkkachu
        3 hours ago








      40




      40





      Whatever layout engine drew that diagram for you has a bug in their minimize-crossings algorithm!

      – Eric Lippert
      21 hours ago





      Whatever layout engine drew that diagram for you has a bug in their minimize-crossings algorithm!

      – Eric Lippert
      21 hours ago




      29




      29





      @EricLippert Could be intentional to emphasize that that the pointees might not be contiguous nor in order.

      – jamesdlin
      17 hours ago





      @EricLippert Could be intentional to emphasize that that the pointees might not be contiguous nor in order.

      – jamesdlin
      17 hours ago




      1




      1





      I would say it's intentional

      – Michael
      16 hours ago





      I would say it's intentional

      – Michael
      16 hours ago




      17




      17





      It was certainly intentional--and I'd guess Eric probably figured that, but (correctly, IMO) thought the comment was funny anyway.

      – Jerry Coffin
      11 hours ago





      It was certainly intentional--and I'd guess Eric probably figured that, but (correctly, IMO) thought the comment was funny anyway.

      – Jerry Coffin
      11 hours ago




      1




      1





      @JerryCoffin, one might also point out that even if the actual arguments were contiguous in memory, they can have arbitrary lengths, so one would still need distinct pointers for each of them to be able to access argv[i] without scanning through all the previous ones.

      – ilkkachu
      3 hours ago





      @JerryCoffin, one might also point out that even if the actual arguments were contiguous in memory, they can have arbitrary lengths, so one would still need distinct pointers for each of them to be able to access argv[i] without scanning through all the previous ones.

      – ilkkachu
      3 hours ago













      15














      Because that's what the operating system provides :-)



      Your question is a little bit of a chicken/egg inversion issue. The problem is not to choose what you want in C++, the problem is how you say in C++ what the OS is giving you.



      Unix passes an array of "strings", each string being a command argument. In C/C++, a string is a "char*", so an array of strings is char* argv, or char** argv, according to taste.






      share|improve this answer








      New contributor




      passer-by is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.
















      • 8





        No, it's exactly "the problem to choose what you want in C++". Windows, for example, provides the command line as a single string, and yet C/C++ programs still receive their argv array — the runtime takes care of tokenizing the command line and building the argv array at the startup.

        – Joker_vD
        yesterday






      • 9





        @Joker_vD I think in a twisted way it is about what the OS gives you. Specifically: I guess C++ did it this way because C did it this way, and C did it this way because at the time C and Unix were so inextricably linked and Unix did it this way.

        – Daniel Wagner
        23 hours ago






      • 1





        @DanielWagner: Yes, this is from C's Unix heritage. On Unix / Linux a minimal _start that calls main just needs to pass main a pointer to the existing argv array in memory; it's already in the right format. The kernel copies it from the argv argument to the execve(const char *filename, char *const argv, char *const envp) system call that was made to start a new executable. (On Linux, argv (the array itself) and argc are on the stack on process entry. I assume most Unixes are the same, because that's a good place for it.)

        – Peter Cordes
        18 hours ago








      • 5





        But Joker's point here is that the C / C++ standards leave it up to the implementation where the args come from; they don't have to be straight from the OS. On an OS that passes a flat string, a good C++ implementation should include tokenizing, instead of setting argc=2 and passing the whole flat string. (Following the letter of the standard is not sufficient to be useful; it intentionally leaves a lot of room for implementation choices.) Although some Windows programs will want to treat quotes specially, so real implementations do provide a way to get the flat string, too.

        – Peter Cordes
        18 hours ago






      • 1





        Basile's answer is pretty much this + @Joker's correction and my comments, with more details.

        – Peter Cordes
        17 hours ago
















      15














      Because that's what the operating system provides :-)



      Your question is a little bit of a chicken/egg inversion issue. The problem is not to choose what you want in C++, the problem is how you say in C++ what the OS is giving you.



      Unix passes an array of "strings", each string being a command argument. In C/C++, a string is a "char*", so an array of strings is char* argv, or char** argv, according to taste.






      share|improve this answer








      New contributor




      passer-by is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.
















      • 8





        No, it's exactly "the problem to choose what you want in C++". Windows, for example, provides the command line as a single string, and yet C/C++ programs still receive their argv array — the runtime takes care of tokenizing the command line and building the argv array at the startup.

        – Joker_vD
        yesterday






      • 9





        @Joker_vD I think in a twisted way it is about what the OS gives you. Specifically: I guess C++ did it this way because C did it this way, and C did it this way because at the time C and Unix were so inextricably linked and Unix did it this way.

        – Daniel Wagner
        23 hours ago






      • 1





        @DanielWagner: Yes, this is from C's Unix heritage. On Unix / Linux a minimal _start that calls main just needs to pass main a pointer to the existing argv array in memory; it's already in the right format. The kernel copies it from the argv argument to the execve(const char *filename, char *const argv, char *const envp) system call that was made to start a new executable. (On Linux, argv (the array itself) and argc are on the stack on process entry. I assume most Unixes are the same, because that's a good place for it.)

        – Peter Cordes
        18 hours ago








      • 5





        But Joker's point here is that the C / C++ standards leave it up to the implementation where the args come from; they don't have to be straight from the OS. On an OS that passes a flat string, a good C++ implementation should include tokenizing, instead of setting argc=2 and passing the whole flat string. (Following the letter of the standard is not sufficient to be useful; it intentionally leaves a lot of room for implementation choices.) Although some Windows programs will want to treat quotes specially, so real implementations do provide a way to get the flat string, too.

        – Peter Cordes
        18 hours ago






      • 1





        Basile's answer is pretty much this + @Joker's correction and my comments, with more details.

        – Peter Cordes
        17 hours ago














      15












      15








      15







      Because that's what the operating system provides :-)



      Your question is a little bit of a chicken/egg inversion issue. The problem is not to choose what you want in C++, the problem is how you say in C++ what the OS is giving you.



      Unix passes an array of "strings", each string being a command argument. In C/C++, a string is a "char*", so an array of strings is char* argv, or char** argv, according to taste.






      share|improve this answer








      New contributor




      passer-by is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.










      Because that's what the operating system provides :-)



      Your question is a little bit of a chicken/egg inversion issue. The problem is not to choose what you want in C++, the problem is how you say in C++ what the OS is giving you.



      Unix passes an array of "strings", each string being a command argument. In C/C++, a string is a "char*", so an array of strings is char* argv, or char** argv, according to taste.







      share|improve this answer








      New contributor




      passer-by is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.









      share|improve this answer



      share|improve this answer






      New contributor




      passer-by is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.









      answered yesterday









      passer-bypasser-by

      1592




      1592




      New contributor




      passer-by is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.





      New contributor





      passer-by is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.






      passer-by is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.








      • 8





        No, it's exactly "the problem to choose what you want in C++". Windows, for example, provides the command line as a single string, and yet C/C++ programs still receive their argv array — the runtime takes care of tokenizing the command line and building the argv array at the startup.

        – Joker_vD
        yesterday






      • 9





        @Joker_vD I think in a twisted way it is about what the OS gives you. Specifically: I guess C++ did it this way because C did it this way, and C did it this way because at the time C and Unix were so inextricably linked and Unix did it this way.

        – Daniel Wagner
        23 hours ago






      • 1





        @DanielWagner: Yes, this is from C's Unix heritage. On Unix / Linux a minimal _start that calls main just needs to pass main a pointer to the existing argv array in memory; it's already in the right format. The kernel copies it from the argv argument to the execve(const char *filename, char *const argv, char *const envp) system call that was made to start a new executable. (On Linux, argv (the array itself) and argc are on the stack on process entry. I assume most Unixes are the same, because that's a good place for it.)

        – Peter Cordes
        18 hours ago








      • 5





        But Joker's point here is that the C / C++ standards leave it up to the implementation where the args come from; they don't have to be straight from the OS. On an OS that passes a flat string, a good C++ implementation should include tokenizing, instead of setting argc=2 and passing the whole flat string. (Following the letter of the standard is not sufficient to be useful; it intentionally leaves a lot of room for implementation choices.) Although some Windows programs will want to treat quotes specially, so real implementations do provide a way to get the flat string, too.

        – Peter Cordes
        18 hours ago






      • 1





        Basile's answer is pretty much this + @Joker's correction and my comments, with more details.

        – Peter Cordes
        17 hours ago














      • 8





        No, it's exactly "the problem to choose what you want in C++". Windows, for example, provides the command line as a single string, and yet C/C++ programs still receive their argv array — the runtime takes care of tokenizing the command line and building the argv array at the startup.

        – Joker_vD
        yesterday






      • 9





        @Joker_vD I think in a twisted way it is about what the OS gives you. Specifically: I guess C++ did it this way because C did it this way, and C did it this way because at the time C and Unix were so inextricably linked and Unix did it this way.

        – Daniel Wagner
        23 hours ago






      • 1





        @DanielWagner: Yes, this is from C's Unix heritage. On Unix / Linux a minimal _start that calls main just needs to pass main a pointer to the existing argv array in memory; it's already in the right format. The kernel copies it from the argv argument to the execve(const char *filename, char *const argv, char *const envp) system call that was made to start a new executable. (On Linux, argv (the array itself) and argc are on the stack on process entry. I assume most Unixes are the same, because that's a good place for it.)

        – Peter Cordes
        18 hours ago








      • 5





        But Joker's point here is that the C / C++ standards leave it up to the implementation where the args come from; they don't have to be straight from the OS. On an OS that passes a flat string, a good C++ implementation should include tokenizing, instead of setting argc=2 and passing the whole flat string. (Following the letter of the standard is not sufficient to be useful; it intentionally leaves a lot of room for implementation choices.) Although some Windows programs will want to treat quotes specially, so real implementations do provide a way to get the flat string, too.

        – Peter Cordes
        18 hours ago






      • 1





        Basile's answer is pretty much this + @Joker's correction and my comments, with more details.

        – Peter Cordes
        17 hours ago








      8




      8





      No, it's exactly "the problem to choose what you want in C++". Windows, for example, provides the command line as a single string, and yet C/C++ programs still receive their argv array — the runtime takes care of tokenizing the command line and building the argv array at the startup.

      – Joker_vD
      yesterday





      No, it's exactly "the problem to choose what you want in C++". Windows, for example, provides the command line as a single string, and yet C/C++ programs still receive their argv array — the runtime takes care of tokenizing the command line and building the argv array at the startup.

      – Joker_vD
      yesterday




      9




      9





      @Joker_vD I think in a twisted way it is about what the OS gives you. Specifically: I guess C++ did it this way because C did it this way, and C did it this way because at the time C and Unix were so inextricably linked and Unix did it this way.

      – Daniel Wagner
      23 hours ago





      @Joker_vD I think in a twisted way it is about what the OS gives you. Specifically: I guess C++ did it this way because C did it this way, and C did it this way because at the time C and Unix were so inextricably linked and Unix did it this way.

      – Daniel Wagner
      23 hours ago




      1




      1





      @DanielWagner: Yes, this is from C's Unix heritage. On Unix / Linux a minimal _start that calls main just needs to pass main a pointer to the existing argv array in memory; it's already in the right format. The kernel copies it from the argv argument to the execve(const char *filename, char *const argv, char *const envp) system call that was made to start a new executable. (On Linux, argv (the array itself) and argc are on the stack on process entry. I assume most Unixes are the same, because that's a good place for it.)

      – Peter Cordes
      18 hours ago







      @DanielWagner: Yes, this is from C's Unix heritage. On Unix / Linux a minimal _start that calls main just needs to pass main a pointer to the existing argv array in memory; it's already in the right format. The kernel copies it from the argv argument to the execve(const char *filename, char *const argv, char *const envp) system call that was made to start a new executable. (On Linux, argv (the array itself) and argc are on the stack on process entry. I assume most Unixes are the same, because that's a good place for it.)

      – Peter Cordes
      18 hours ago






      5




      5





      But Joker's point here is that the C / C++ standards leave it up to the implementation where the args come from; they don't have to be straight from the OS. On an OS that passes a flat string, a good C++ implementation should include tokenizing, instead of setting argc=2 and passing the whole flat string. (Following the letter of the standard is not sufficient to be useful; it intentionally leaves a lot of room for implementation choices.) Although some Windows programs will want to treat quotes specially, so real implementations do provide a way to get the flat string, too.

      – Peter Cordes
      18 hours ago





      But Joker's point here is that the C / C++ standards leave it up to the implementation where the args come from; they don't have to be straight from the OS. On an OS that passes a flat string, a good C++ implementation should include tokenizing, instead of setting argc=2 and passing the whole flat string. (Following the letter of the standard is not sufficient to be useful; it intentionally leaves a lot of room for implementation choices.) Although some Windows programs will want to treat quotes specially, so real implementations do provide a way to get the flat string, too.

      – Peter Cordes
      18 hours ago




      1




      1





      Basile's answer is pretty much this + @Joker's correction and my comments, with more details.

      – Peter Cordes
      17 hours ago





      Basile's answer is pretty much this + @Joker's correction and my comments, with more details.

      – Peter Cordes
      17 hours ago











      11














      First, as a parameter declaration, char **argv is the same as char *argv; they both imply a pointer to (an array or set of one or more possible) pointer(s) to strings.



      Next, if you only have "pointer to char" (e.g. just char *, then in order to access the nth item, you'll have to scan the first n-1 items to find the nth item's start.  (And this would also impose the requirement that each of the strings are stored contiguously.)



      With the array of pointers, you can directly index the nth item — so (while not strictly necessary — assuming the strings are contiguous) it is generally much more convenient.



      To illustrate:



      ./program hello world



      argc = 3
      argv[0] --> "./program"
      argv[1] --> "hello"
      argv[2] --> "world"


      It is possible that, in an os provided array of characters:



                  "./programhelloworld"
      argv[0] ^
      argv[1] ^
      argv[2] ^


      if argv were just a "pointer to char" you might see



             "./programhelloworld"
      argv ^


      However (though likely by design of the os) there is no real guarantee that the three strings "./program", "hello", and "world" are contiguous.  Further, this kind of "single pointer to multiple contiguous strings" is a more unusual data type construct (for C), especially compared with array of pointers to string.






      share|improve this answer


























      • what if instead of , argv --> "helloworld" you have argv --> index 0 of the array (hello), just like a normal array. why isn't this doable? then you keep reading the array argc times. then you pass argv itself and not a pointer to argv.

        – a user
        yesterday













      • @auser, that's what argv --> "./programhelloworld" is: a pointer to the first char (i.e. the ".") If you take that pointer past the first , then you have a pointer to "hello", and after that to "world". After argc times (hitting "), you're done. Sure, it can be made to work, and as I said, an unusual construct.

        – Erik Eidt
        yesterday











      • You forgot to state that in your example argv[4] is NULL

        – Basile Starynkevitch
        yesterday











      • @BasileStarynkevitch, oh, ok!

        – Erik Eidt
        yesterday






      • 2





        There is a guarantee that (at least initially) argv[argc] == NULL. In this case that's argv[3], not argv[4].

        – Miral
        8 hours ago
















      11














      First, as a parameter declaration, char **argv is the same as char *argv; they both imply a pointer to (an array or set of one or more possible) pointer(s) to strings.



      Next, if you only have "pointer to char" (e.g. just char *, then in order to access the nth item, you'll have to scan the first n-1 items to find the nth item's start.  (And this would also impose the requirement that each of the strings are stored contiguously.)



      With the array of pointers, you can directly index the nth item — so (while not strictly necessary — assuming the strings are contiguous) it is generally much more convenient.



      To illustrate:



      ./program hello world



      argc = 3
      argv[0] --> "./program"
      argv[1] --> "hello"
      argv[2] --> "world"


      It is possible that, in an os provided array of characters:



                  "./programhelloworld"
      argv[0] ^
      argv[1] ^
      argv[2] ^


      if argv were just a "pointer to char" you might see



             "./programhelloworld"
      argv ^


      However (though likely by design of the os) there is no real guarantee that the three strings "./program", "hello", and "world" are contiguous.  Further, this kind of "single pointer to multiple contiguous strings" is a more unusual data type construct (for C), especially compared with array of pointers to string.






      share|improve this answer


























      • what if instead of , argv --> "helloworld" you have argv --> index 0 of the array (hello), just like a normal array. why isn't this doable? then you keep reading the array argc times. then you pass argv itself and not a pointer to argv.

        – a user
        yesterday













      • @auser, that's what argv --> "./programhelloworld" is: a pointer to the first char (i.e. the ".") If you take that pointer past the first , then you have a pointer to "hello", and after that to "world". After argc times (hitting "), you're done. Sure, it can be made to work, and as I said, an unusual construct.

        – Erik Eidt
        yesterday











      • You forgot to state that in your example argv[4] is NULL

        – Basile Starynkevitch
        yesterday











      • @BasileStarynkevitch, oh, ok!

        – Erik Eidt
        yesterday






      • 2





        There is a guarantee that (at least initially) argv[argc] == NULL. In this case that's argv[3], not argv[4].

        – Miral
        8 hours ago














      11












      11








      11







      First, as a parameter declaration, char **argv is the same as char *argv; they both imply a pointer to (an array or set of one or more possible) pointer(s) to strings.



      Next, if you only have "pointer to char" (e.g. just char *, then in order to access the nth item, you'll have to scan the first n-1 items to find the nth item's start.  (And this would also impose the requirement that each of the strings are stored contiguously.)



      With the array of pointers, you can directly index the nth item — so (while not strictly necessary — assuming the strings are contiguous) it is generally much more convenient.



      To illustrate:



      ./program hello world



      argc = 3
      argv[0] --> "./program"
      argv[1] --> "hello"
      argv[2] --> "world"


      It is possible that, in an os provided array of characters:



                  "./programhelloworld"
      argv[0] ^
      argv[1] ^
      argv[2] ^


      if argv were just a "pointer to char" you might see



             "./programhelloworld"
      argv ^


      However (though likely by design of the os) there is no real guarantee that the three strings "./program", "hello", and "world" are contiguous.  Further, this kind of "single pointer to multiple contiguous strings" is a more unusual data type construct (for C), especially compared with array of pointers to string.






      share|improve this answer















      First, as a parameter declaration, char **argv is the same as char *argv; they both imply a pointer to (an array or set of one or more possible) pointer(s) to strings.



      Next, if you only have "pointer to char" (e.g. just char *, then in order to access the nth item, you'll have to scan the first n-1 items to find the nth item's start.  (And this would also impose the requirement that each of the strings are stored contiguously.)



      With the array of pointers, you can directly index the nth item — so (while not strictly necessary — assuming the strings are contiguous) it is generally much more convenient.



      To illustrate:



      ./program hello world



      argc = 3
      argv[0] --> "./program"
      argv[1] --> "hello"
      argv[2] --> "world"


      It is possible that, in an os provided array of characters:



                  "./programhelloworld"
      argv[0] ^
      argv[1] ^
      argv[2] ^


      if argv were just a "pointer to char" you might see



             "./programhelloworld"
      argv ^


      However (though likely by design of the os) there is no real guarantee that the three strings "./program", "hello", and "world" are contiguous.  Further, this kind of "single pointer to multiple contiguous strings" is a more unusual data type construct (for C), especially compared with array of pointers to string.







      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited 22 hours ago

























      answered yesterday









      Erik EidtErik Eidt

      22.8k43160




      22.8k43160













      • what if instead of , argv --> "helloworld" you have argv --> index 0 of the array (hello), just like a normal array. why isn't this doable? then you keep reading the array argc times. then you pass argv itself and not a pointer to argv.

        – a user
        yesterday













      • @auser, that's what argv --> "./programhelloworld" is: a pointer to the first char (i.e. the ".") If you take that pointer past the first , then you have a pointer to "hello", and after that to "world". After argc times (hitting "), you're done. Sure, it can be made to work, and as I said, an unusual construct.

        – Erik Eidt
        yesterday











      • You forgot to state that in your example argv[4] is NULL

        – Basile Starynkevitch
        yesterday











      • @BasileStarynkevitch, oh, ok!

        – Erik Eidt
        yesterday






      • 2





        There is a guarantee that (at least initially) argv[argc] == NULL. In this case that's argv[3], not argv[4].

        – Miral
        8 hours ago



















      • what if instead of , argv --> "helloworld" you have argv --> index 0 of the array (hello), just like a normal array. why isn't this doable? then you keep reading the array argc times. then you pass argv itself and not a pointer to argv.

        – a user
        yesterday













      • @auser, that's what argv --> "./programhelloworld" is: a pointer to the first char (i.e. the ".") If you take that pointer past the first , then you have a pointer to "hello", and after that to "world". After argc times (hitting "), you're done. Sure, it can be made to work, and as I said, an unusual construct.

        – Erik Eidt
        yesterday











      • You forgot to state that in your example argv[4] is NULL

        – Basile Starynkevitch
        yesterday











      • @BasileStarynkevitch, oh, ok!

        – Erik Eidt
        yesterday






      • 2





        There is a guarantee that (at least initially) argv[argc] == NULL. In this case that's argv[3], not argv[4].

        – Miral
        8 hours ago

















      what if instead of , argv --> "helloworld" you have argv --> index 0 of the array (hello), just like a normal array. why isn't this doable? then you keep reading the array argc times. then you pass argv itself and not a pointer to argv.

      – a user
      yesterday







      what if instead of , argv --> "helloworld" you have argv --> index 0 of the array (hello), just like a normal array. why isn't this doable? then you keep reading the array argc times. then you pass argv itself and not a pointer to argv.

      – a user
      yesterday















      @auser, that's what argv --> "./programhelloworld" is: a pointer to the first char (i.e. the ".") If you take that pointer past the first , then you have a pointer to "hello", and after that to "world". After argc times (hitting "), you're done. Sure, it can be made to work, and as I said, an unusual construct.

      – Erik Eidt
      yesterday





      @auser, that's what argv --> "./programhelloworld" is: a pointer to the first char (i.e. the ".") If you take that pointer past the first , then you have a pointer to "hello", and after that to "world". After argc times (hitting "), you're done. Sure, it can be made to work, and as I said, an unusual construct.

      – Erik Eidt
      yesterday













      You forgot to state that in your example argv[4] is NULL

      – Basile Starynkevitch
      yesterday





      You forgot to state that in your example argv[4] is NULL

      – Basile Starynkevitch
      yesterday













      @BasileStarynkevitch, oh, ok!

      – Erik Eidt
      yesterday





      @BasileStarynkevitch, oh, ok!

      – Erik Eidt
      yesterday




      2




      2





      There is a guarantee that (at least initially) argv[argc] == NULL. In this case that's argv[3], not argv[4].

      – Miral
      8 hours ago





      There is a guarantee that (at least initially) argv[argc] == NULL. In this case that's argv[3], not argv[4].

      – Miral
      8 hours ago











      10















      Why C/C++ main argv is declared as “char* argv”




      A possible answer is because the C11 standard n1570 (in §5.1.2.2.1 Program startup) and the C++11 standard n3337 (in §3.6.1 main function) require that for hosted environments (but notice that the C standard mentions also §5.1.2.1 freestanding environments) See also this.



      The next question is why did the C and C++ standards choose main to have such a int main(int argc, char**argv) signature? The explanation is largely historical: C was invented with Unix, which has a shell which does globbing before doing fork (which is a system call to create a process) and execve (which is the system call to execute a program), and that execve transmits an array of string program arguments and is related to the main of the executed program. Read more about the Unix philosophy and about ABIs.



      And C++ tried hard to follow the conventions of C and be compatible with it. It could not define main to be incompatible with C traditions.



      If you designed an operating system from scratch (still having a command line interface) and a programming language for it from scratch, you'll be free to invent different program starting conventions. And other programming languages (e.g. Common Lisp or Ocaml or Go) have different program starting conventions.



      In practice, main is invoked by some crt0 code. Notice that on Windows the globbing may be done by each program in the equivalent of crt0, and some Windows programs can start thru the non-standard WinMain entry point. On Unix, globbing is done by the shell (and crt0 is adapting the ABI, and the initial call stack layout that it has specified, to calling conventions of your C implementation).






      share|improve this answer






























        10















        Why C/C++ main argv is declared as “char* argv”




        A possible answer is because the C11 standard n1570 (in §5.1.2.2.1 Program startup) and the C++11 standard n3337 (in §3.6.1 main function) require that for hosted environments (but notice that the C standard mentions also §5.1.2.1 freestanding environments) See also this.



        The next question is why did the C and C++ standards choose main to have such a int main(int argc, char**argv) signature? The explanation is largely historical: C was invented with Unix, which has a shell which does globbing before doing fork (which is a system call to create a process) and execve (which is the system call to execute a program), and that execve transmits an array of string program arguments and is related to the main of the executed program. Read more about the Unix philosophy and about ABIs.



        And C++ tried hard to follow the conventions of C and be compatible with it. It could not define main to be incompatible with C traditions.



        If you designed an operating system from scratch (still having a command line interface) and a programming language for it from scratch, you'll be free to invent different program starting conventions. And other programming languages (e.g. Common Lisp or Ocaml or Go) have different program starting conventions.



        In practice, main is invoked by some crt0 code. Notice that on Windows the globbing may be done by each program in the equivalent of crt0, and some Windows programs can start thru the non-standard WinMain entry point. On Unix, globbing is done by the shell (and crt0 is adapting the ABI, and the initial call stack layout that it has specified, to calling conventions of your C implementation).






        share|improve this answer




























          10












          10








          10








          Why C/C++ main argv is declared as “char* argv”




          A possible answer is because the C11 standard n1570 (in §5.1.2.2.1 Program startup) and the C++11 standard n3337 (in §3.6.1 main function) require that for hosted environments (but notice that the C standard mentions also §5.1.2.1 freestanding environments) See also this.



          The next question is why did the C and C++ standards choose main to have such a int main(int argc, char**argv) signature? The explanation is largely historical: C was invented with Unix, which has a shell which does globbing before doing fork (which is a system call to create a process) and execve (which is the system call to execute a program), and that execve transmits an array of string program arguments and is related to the main of the executed program. Read more about the Unix philosophy and about ABIs.



          And C++ tried hard to follow the conventions of C and be compatible with it. It could not define main to be incompatible with C traditions.



          If you designed an operating system from scratch (still having a command line interface) and a programming language for it from scratch, you'll be free to invent different program starting conventions. And other programming languages (e.g. Common Lisp or Ocaml or Go) have different program starting conventions.



          In practice, main is invoked by some crt0 code. Notice that on Windows the globbing may be done by each program in the equivalent of crt0, and some Windows programs can start thru the non-standard WinMain entry point. On Unix, globbing is done by the shell (and crt0 is adapting the ABI, and the initial call stack layout that it has specified, to calling conventions of your C implementation).






          share|improve this answer
















          Why C/C++ main argv is declared as “char* argv”




          A possible answer is because the C11 standard n1570 (in §5.1.2.2.1 Program startup) and the C++11 standard n3337 (in §3.6.1 main function) require that for hosted environments (but notice that the C standard mentions also §5.1.2.1 freestanding environments) See also this.



          The next question is why did the C and C++ standards choose main to have such a int main(int argc, char**argv) signature? The explanation is largely historical: C was invented with Unix, which has a shell which does globbing before doing fork (which is a system call to create a process) and execve (which is the system call to execute a program), and that execve transmits an array of string program arguments and is related to the main of the executed program. Read more about the Unix philosophy and about ABIs.



          And C++ tried hard to follow the conventions of C and be compatible with it. It could not define main to be incompatible with C traditions.



          If you designed an operating system from scratch (still having a command line interface) and a programming language for it from scratch, you'll be free to invent different program starting conventions. And other programming languages (e.g. Common Lisp or Ocaml or Go) have different program starting conventions.



          In practice, main is invoked by some crt0 code. Notice that on Windows the globbing may be done by each program in the equivalent of crt0, and some Windows programs can start thru the non-standard WinMain entry point. On Unix, globbing is done by the shell (and crt0 is adapting the ABI, and the initial call stack layout that it has specified, to calling conventions of your C implementation).







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited 12 hours ago

























          answered yesterday









          Basile StarynkevitchBasile Starynkevitch

          27.7k562102




          27.7k562102























              9














              Rather than thinking of it as "pointer to pointer", it helps to think of it as "array of strings", with denoting array and char* denoting string. When you run a program, you can pass it one or more command-line arguments and these are reflected in the arguments to main: argc is the count of arguments and argv lets you access individual arguments.






              share|improve this answer



















              • 2





                +1 This! In many languages - bash, PHP, C, C++ - argv is an array of strings. Of this you have to think when you see char ** or char *, which is the same.

                – rexkogitans
                23 hours ago
















              9














              Rather than thinking of it as "pointer to pointer", it helps to think of it as "array of strings", with denoting array and char* denoting string. When you run a program, you can pass it one or more command-line arguments and these are reflected in the arguments to main: argc is the count of arguments and argv lets you access individual arguments.






              share|improve this answer



















              • 2





                +1 This! In many languages - bash, PHP, C, C++ - argv is an array of strings. Of this you have to think when you see char ** or char *, which is the same.

                – rexkogitans
                23 hours ago














              9












              9








              9







              Rather than thinking of it as "pointer to pointer", it helps to think of it as "array of strings", with denoting array and char* denoting string. When you run a program, you can pass it one or more command-line arguments and these are reflected in the arguments to main: argc is the count of arguments and argv lets you access individual arguments.






              share|improve this answer













              Rather than thinking of it as "pointer to pointer", it helps to think of it as "array of strings", with denoting array and char* denoting string. When you run a program, you can pass it one or more command-line arguments and these are reflected in the arguments to main: argc is the count of arguments and argv lets you access individual arguments.







              share|improve this answer












              share|improve this answer



              share|improve this answer










              answered yesterday









              casablancacasablanca

              77437




              77437








              • 2





                +1 This! In many languages - bash, PHP, C, C++ - argv is an array of strings. Of this you have to think when you see char ** or char *, which is the same.

                – rexkogitans
                23 hours ago














              • 2





                +1 This! In many languages - bash, PHP, C, C++ - argv is an array of strings. Of this you have to think when you see char ** or char *, which is the same.

                – rexkogitans
                23 hours ago








              2




              2





              +1 This! In many languages - bash, PHP, C, C++ - argv is an array of strings. Of this you have to think when you see char ** or char *, which is the same.

              – rexkogitans
              23 hours ago





              +1 This! In many languages - bash, PHP, C, C++ - argv is an array of strings. Of this you have to think when you see char ** or char *, which is the same.

              – rexkogitans
              23 hours ago











              1














              In many cases the answer is "because it's a standard". To quote C99 standard:




              — If the value of argc is greater than zero, the array members argv[0] through
              argv[argc-1] inclusive shall contain pointers to strings, which are given
              implementation-defined values by the host environment prior to program startup.




              Of course, before it has been standardized it was already in use by K&R C in early Unix implementations, with the purpose of storing command-line parameters (something you have to care in Unix shell such as /bin/bash or /bin/sh but not in embedded systems). To quote first edition of K&R's "The C Programming Language" (pg. 110):




              The first (conventionally called argc) is the number of command-line arguments the program was invoked with; the second (argv) is a pointer to an array of character strings that contain the arguments, one per string.







              share|improve this answer










              New contributor




              Sergiy Kolodyazhnyy is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
              Check out our Code of Conduct.

























                1














                In many cases the answer is "because it's a standard". To quote C99 standard:




                — If the value of argc is greater than zero, the array members argv[0] through
                argv[argc-1] inclusive shall contain pointers to strings, which are given
                implementation-defined values by the host environment prior to program startup.




                Of course, before it has been standardized it was already in use by K&R C in early Unix implementations, with the purpose of storing command-line parameters (something you have to care in Unix shell such as /bin/bash or /bin/sh but not in embedded systems). To quote first edition of K&R's "The C Programming Language" (pg. 110):




                The first (conventionally called argc) is the number of command-line arguments the program was invoked with; the second (argv) is a pointer to an array of character strings that contain the arguments, one per string.







                share|improve this answer










                New contributor




                Sergiy Kolodyazhnyy is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                Check out our Code of Conduct.























                  1












                  1








                  1







                  In many cases the answer is "because it's a standard". To quote C99 standard:




                  — If the value of argc is greater than zero, the array members argv[0] through
                  argv[argc-1] inclusive shall contain pointers to strings, which are given
                  implementation-defined values by the host environment prior to program startup.




                  Of course, before it has been standardized it was already in use by K&R C in early Unix implementations, with the purpose of storing command-line parameters (something you have to care in Unix shell such as /bin/bash or /bin/sh but not in embedded systems). To quote first edition of K&R's "The C Programming Language" (pg. 110):




                  The first (conventionally called argc) is the number of command-line arguments the program was invoked with; the second (argv) is a pointer to an array of character strings that contain the arguments, one per string.







                  share|improve this answer










                  New contributor




                  Sergiy Kolodyazhnyy is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                  Check out our Code of Conduct.










                  In many cases the answer is "because it's a standard". To quote C99 standard:




                  — If the value of argc is greater than zero, the array members argv[0] through
                  argv[argc-1] inclusive shall contain pointers to strings, which are given
                  implementation-defined values by the host environment prior to program startup.




                  Of course, before it has been standardized it was already in use by K&R C in early Unix implementations, with the purpose of storing command-line parameters (something you have to care in Unix shell such as /bin/bash or /bin/sh but not in embedded systems). To quote first edition of K&R's "The C Programming Language" (pg. 110):




                  The first (conventionally called argc) is the number of command-line arguments the program was invoked with; the second (argv) is a pointer to an array of character strings that contain the arguments, one per string.








                  share|improve this answer










                  New contributor




                  Sergiy Kolodyazhnyy is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                  Check out our Code of Conduct.









                  share|improve this answer



                  share|improve this answer








                  edited yesterday





















                  New contributor




                  Sergiy Kolodyazhnyy is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                  Check out our Code of Conduct.









                  answered yesterday









                  Sergiy KolodyazhnyySergiy Kolodyazhnyy

                  1194




                  1194




                  New contributor




                  Sergiy Kolodyazhnyy is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                  Check out our Code of Conduct.





                  New contributor





                  Sergiy Kolodyazhnyy is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                  Check out our Code of Conduct.






                  Sergiy Kolodyazhnyy is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                  Check out our Code of Conduct.






















                      a user is a new contributor. Be nice, and check out our Code of Conduct.










                      draft saved

                      draft discarded


















                      a user is a new contributor. Be nice, and check out our Code of Conduct.













                      a user is a new contributor. Be nice, and check out our Code of Conduct.












                      a user is a new contributor. Be nice, and check out our Code of Conduct.
















                      Thanks for contributing an answer to Software Engineering Stack Exchange!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsoftwareengineering.stackexchange.com%2fquestions%2f385819%2fwhy-is-c-c-main-argv-declared-as-char-argv-rather-than-just-char-argv%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown











                      Popular posts from this blog

                      How to label and detect the document text images

                      Vallis Paradisi

                      Tabula Rosettana