function (const char *) vs. function (char *)

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • andrew.fabbro@gmail.com

    #1

    function (const char *) vs. function (char *)

    In a different newsgroup, I was told that a function I'd written that
    looked like this:

    void myfunc (char * somestring_ptr)

    should instead be

    void myfunc (const char * somestring_ptr)

    When I asked why, I was told that it facilitated calling it as:

    myfunc ("String");

    instead of

    strcpy (string, "What I want");
    myfunc (string);

    However, now that I experiment with it, I find that my original
    prototype

    void myfunc (char * somestring_ptr)

    works perfectly well with either invocation.

    So I'm curious why "const char *" would be desirable?

    The only difference I see it makes is that it forbids modification of
    the string within the function...of course, you can't modify the
    original copy of the string, since C is call-by-value, but I guess
    const char * means you can't modify the passed copy in the function
    either...perhap s this is just an additional safeguard?

    I'm curious if there is something I'm missing about "const char *" in
    function prototypes. K&R doesn't mention anything about this (though
    of course some of the library functions do use "const char *").

    Thanks,

    -AF

  • tedu

    #2
    Re: function (const char *) vs. function (char *)


    andrew.fabbro@g mail.com wrote:[color=blue]
    > In a different newsgroup, I was told that a function I'd written that
    > looked like this:
    >
    > void myfunc (char * somestring_ptr)
    >
    > should instead be
    >
    > void myfunc (const char * somestring_ptr)
    >[/color]
    ....[color=blue]
    > So I'm curious why "const char *" would be desirable?[/color]

    So that you don't accidentally modify the value. Also, it allows a
    caller to pass a const char * as an argument. Not to mention it
    demonstrates to anyone using the function that it's not going to modify
    their string if they care about it.
    [color=blue]
    > The only difference I see it makes is that it forbids modification of
    > the string within the function...of course, you can't modify the
    > original copy of the string, since C is call-by-value, but I guess
    > const char * means you can't modify the passed copy in the function
    > either...perhap s this is just an additional safeguard?[/color]

    The pointer value is passed by value, but the contents of the string,
    the characters, are not. The const keyword applies to the chars, not
    the pointer.

    Comment

    • Eric Sosman

      #3
      Re: function (const char *) vs. function (char *)

      andrew.fabbro@g mail.com wrote:[color=blue]
      > In a different newsgroup, I was told that a function I'd written that
      > looked like this:
      >
      > void myfunc (char * somestring_ptr)
      >
      > should instead be
      >
      > void myfunc (const char * somestring_ptr)
      >
      > When I asked why, I was told that it facilitated calling it as:
      >
      > myfunc ("String");
      >
      > instead of
      >
      > strcpy (string, "What I want");
      > myfunc (string);[/color]

      Whoever told you that didn't know C. The type of "String"
      is `char*', not `const char*', so you can pass it to myfunc()
      (either edition) without any trouble.

      (Why isn't "String" a `const char*'? Historical reasons:
      pre-Standard C had no `const', so all functions with string
      arguments looked like your original no matter whether they
      intended to modify the string argument or not. If the Standard
      had made character literals `const*', all pre-existing functions
      would have suddenly become unable to accept string literals as
      arguments. This would have raised a serious barrier to the
      adoption of the Standard -- and the writers of the Standard were,
      naturally, not interested in raising such barriers.)
      [color=blue]
      > However, now that I experiment with it, I find that my original
      > prototype
      >
      > void myfunc (char * somestring_ptr)
      >
      > works perfectly well with either invocation.[/color]

      As it should. Now that you know that "String" is not
      const-qualified, you surely understand why.
      [color=blue]
      > So I'm curious why "const char *" would be desirable?[/color]

      Mostly as documentation: A function that describes its argument
      as `const char*' is promising not to modify the pointed-to string,
      while a function that takes a plain `char*' either (1) leaves the
      question open if it's "old code," or (2) suggests that it actually
      may modify the string.

      Unfortunately, the "promise" of `const char*' is violable. You
      could perfectly well write a function like

      void myfunc(const char *unmodifiable) {
      char *gotcha = (char*)unmodifi able;
      *gotcha = '\0';
      }

      .... thus in a sense lying to your clients. The language permits
      such things -- it pretty much has to, if functions like strchr()
      are to be written in C -- but, of course, You would Never do Such
      A Thing. I hope. Use `conat char*' (more generally, `const T*')
      whenever your function has no reason to want to modify the pointed-
      to thing; use plain `char*' (`T*') when it might. The people who
      write calls to your functions will thank you for your helpfulness.
      [color=blue]
      > The only difference I see it makes is that it forbids modification of
      > the string within the function...of course, you can't modify the
      > original copy of the string, since C is call-by-value, but I guess
      > const char * means you can't modify the passed copy in the function
      > either...perhap s this is just an additional safeguard?[/color]

      Some of your language makes me a little queasy, and makes me
      wonder if your grasp of C's argument-passing is as firm as it might
      be. Remember always: The string itself is not "passed" to the
      function, not ever. What the function receives is a pointer to the
      first character of the string, while the string itself continues to
      exist "outside." Since C uses call-by-value the function is free
      to modify the pointer value it receives, and this modification will
      not affect the caller. But even without modifying the pointer, the
      function can use it to modify the pointed-to string -- except that
      if the argument is `const'-qualified you've promised not to do so
      (and the compiler will complain if you try, in the absence of the
      sort of shenanigans shown above).
      [color=blue]
      > I'm curious if there is something I'm missing about "const char *" in
      > function prototypes. K&R doesn't mention anything about this (though
      > of course some of the library functions do use "const char *").[/color]

      If you think `const' is hard to understand, just wait until
      you encounter `restrict' ;-)

      --
      Eric Sosman
      esosman@acm.org .invalid

      Comment

      • Ian

        #4
        Re: function (const char *) vs. function (char *)

        andrew.fabbro@g mail.com wrote:[color=blue]
        > In a different newsgroup, I was told that a function I'd written that
        > looked like this:
        >
        > void myfunc (char * somestring_ptr)
        >
        > should instead be
        >
        > void myfunc (const char * somestring_ptr)
        >
        > When I asked why, I was told that it facilitated calling it as:
        >
        > myfunc ("String");
        >
        > instead of
        >
        > strcpy (string, "What I want");
        > myfunc (string);
        >
        > However, now that I experiment with it, I find that my original
        > prototype
        >
        > void myfunc (char * somestring_ptr)
        >
        > works perfectly well with either invocation.
        >
        > So I'm curious why "const char *" would be desirable?
        >
        > The only difference I see it makes is that it forbids modification of
        > the string within the function...of course, you can't modify the
        > original copy of the string, since C is call-by-value, but I guess
        > const char * means you can't modify the passed copy in the function
        > either...perhap s this is just an additional safeguard?
        >[/color]
        In these cases, you are passing a pointer by value, not what it points to!

        So if you function takes a char*, it can and by implication, will modify
        the data pointed to. This can give all sorts of undefined results if a
        string literal is passed.

        Ian

        Comment

        • Peter Nilsson

          #5
          Re: function (const char *) vs. function (char *)

          andrew.fabbro@g mail.com wrote:[color=blue]
          > In a different newsgroup, I was told that a function I'd written
          > that looked like this:
          >
          > void myfunc (char * somestring_ptr)
          >
          > should instead be
          >
          > void myfunc (const char * somestring_ptr)
          >
          > When I asked why, I was told that it facilitated calling it as:
          >
          > myfunc ("String");
          >
          > instead of
          >
          > strcpy (string, "What I want");
          > myfunc (string);
          >
          > However, now that I experiment with it, I find that my original
          > prototype
          >
          > void myfunc (char * somestring_ptr)
          >
          > works perfectly well with either invocation.[/color]

          The cited reason is a poor one since (for historical reasons) the
          type of string literals is char[], not const char[]. Modifying the
          contents of a string literal invokes undefined behaviour, but
          the sample will not illustrate this properly on some platforms.

          A better example would be...

          const char fixed[] = "This string won't or shouldn't change.";
          myfunc(fixed);

          If myfunc doesn't attempt to modify the character array, then
          making the parameter point to a const qualified character will
          make your code arguably more robust. Why? Because if you do
          accidentally(?! ) modify the array using your parameter pointer,
          then the compiler is required to issue a diagnostic (warning/
          error.) So the const potentially guards against some logic
          errors.

          That said, there are some arguments against using const at
          all in C. [Google for 'const poisoning', and check out the
          reasons why functions like strpbrk (et all) take a const
          qualified pointer, but return a non-const pointer.]

          --
          Peter

          Comment

          • kar1107@gmail.com

            #6
            Re: function (const char *) vs. function (char *)


            andrew.fabbro@g mail.com wrote:[color=blue]
            > In a different newsgroup, I was told that a function I'd written that
            > looked like this:
            >
            > void myfunc (char * somestring_ptr)
            >
            > should instead be
            >
            > void myfunc (const char * somestring_ptr)
            >
            > When I asked why, I was told that it facilitated calling it as:
            >
            > myfunc ("String");
            >
            > instead of
            >
            > strcpy (string, "What I want");
            > myfunc (string);
            >
            > However, now that I experiment with it, I find that my original
            > prototype
            >
            > void myfunc (char * somestring_ptr)
            >
            > works perfectly well with either invocation.
            >
            > So I'm curious why "const char *" would be desirable?
            >[/color]

            Like others pointed out there is really nothing wrong in not
            using const. But gcc (assuming you are using it) will emit
            warnings if you turn on -Wwrite-strings.
            Google for "initializa tion discards qualifiers" and you can find more
            info

            Karthik
            [color=blue]
            > The only difference I see it makes is that it forbids modification of
            > the string within the function...of course, you can't modify the
            > original copy of the string, since C is call-by-value, but I guess
            > const char * means you can't modify the passed copy in the function
            > either...perhap s this is just an additional safeguard?
            >
            > I'm curious if there is something I'm missing about "const char *" in
            > function prototypes. K&R doesn't mention anything about this (though
            > of course some of the library functions do use "const char *").
            >
            > Thanks,
            >
            > -AF[/color]

            Comment

            • Lawrence Kirby

              #7
              Re: function (const char *) vs. function (char *)

              On Tue, 23 Aug 2005 20:59:41 -0400, Eric Sosman wrote:
              [color=blue]
              > andrew.fabbro@g mail.com wrote:[color=green]
              >> In a different newsgroup, I was told that a function I'd written that
              >> looked like this:
              >>
              >> void myfunc (char * somestring_ptr)
              >>
              >> should instead be
              >>
              >> void myfunc (const char * somestring_ptr)
              >>
              >> When I asked why, I was told that it facilitated calling it as:
              >>
              >> myfunc ("String");
              >>
              >> instead of
              >>
              >> strcpy (string, "What I want");
              >> myfunc (string);[/color]
              >
              > Whoever told you that didn't know C. The type of "String"
              > is `char*', not `const char*', so you can pass it to myfunc()
              > (either edition) without any trouble.[/color]

              The type of "string" is char [7], it is an array of char not a pointer. Of
              course like other arrays it is converted to a pointer to its first element
              in most contexts including when used as a function argument.



              [color=blue]
              >
              > (Why isn't "String" a `const char*'? Historical reasons:
              > pre-Standard C had no `const', so all functions with string
              > arguments looked like your original no matter whether they
              > intended to modify the string argument or not. If the Standard
              > had made character literals `const*', all pre-existing functions
              > would have suddenly become unable to accept string literals as
              > arguments. This would have raised a serious barrier to the
              > adoption of the Standard -- and the writers of the Standard were,
              > naturally, not interested in raising such barriers.)
              >[color=green]
              >> However, now that I experiment with it, I find that my original
              >> prototype
              >>
              >> void myfunc (char * somestring_ptr)
              >>
              >> works perfectly well with either invocation.[/color]
              >
              > As it should. Now that you know that "String" is not
              > const-qualified, you surely understand why.
              >[color=green]
              >> So I'm curious why "const char *" would be desirable?[/color]
              >
              > Mostly as documentation: A function that describes its argument
              > as `const char*' is promising not to modify the pointed-to string,
              > while a function that takes a plain `char*' either (1) leaves the
              > question open if it's "old code," or (2) suggests that it actually
              > may modify the string.[/color]

              But it is "documentat ion" that the compiler can check to some degree. If
              you have a pointer variable in your function of type const char * you cn
              pass it directly to a function that takes a const char * argument but not
              to one that takes a char * argument. Similarly for a const array of char
              although that isn't as common.
              [color=blue]
              > Unfortunately, the "promise" of `const char*' is violable. You
              > could perfectly well write a function like
              >
              > void myfunc(const char *unmodifiable) {
              > char *gotcha = (char*)unmodifi able;
              > *gotcha = '\0';
              > }
              >
              > ... thus in a sense lying to your clients. The language permits
              > such things -- it pretty much has to, if functions like strchr()
              > are to be written in C -- but, of course, You would Never do Such
              > A Thing. I hope. Use `conat char*' (more generally, `const T*')
              > whenever your function has no reason to want to modify the pointed-
              > to thing; use plain `char*' (`T*') when it might. The people who
              > write calls to your functions will thank you for your helpfulness.[/color]

              Right, it is a matter of the interface specification. It is a normal
              convention that when a function takes a pointer to const argument it won't
              attempt to modify what the pointer points at. If this is the convention
              used and the called function breaks it then the called function is broken.
              As you say const here is documentation, but it provides some enforcable
              checks, although not complete guarantees. The called function typically
              has to use a nasty/suspicious construct like a pointer cast to get around
              it.

              Because string literals are not modifiable passing one to a function
              taking a pointer to non-const char should be considered suspicious but
              this is something you have to check yourself because it is valid as far as
              C is concerned, or you find a compiler or lint tol that check for it as
              something extra.

              Lawrence


              Comment

              • Tim Rentsch

                #8
                Re: function (const char *) vs. function (char *)

                andrew.fabbro@g mail.com writes:
                [color=blue]
                > In a different newsgroup, I was told that a function I'd written that
                > looked like this:
                >
                > void myfunc (char * somestring_ptr)
                >
                > should instead be
                >
                > void myfunc (const char * somestring_ptr)
                >
                > When I asked why, I was told that it facilitated calling it as:
                >
                > myfunc ("String");
                >
                > instead of
                >
                > strcpy (string, "What I want");
                > myfunc (string);
                >
                > However, now that I experiment with it, I find that my original
                > prototype
                >
                > void myfunc (char * somestring_ptr)
                >
                > works perfectly well with either invocation.
                >
                > So I'm curious why "const char *" would be desirable?[/color]

                In cases where a parameter can be made 'const char *' rather
                than just 'char *', and that doesn't affect the return type
                of the function (or other similar kinds of ripple effects),
                I almost always prefer to make the parameter the more
                restrictive (that is, const) type.

                The reason is, besides giving more guarantees to clients
                about what will be done with what their pointer points to,
                it makes it easier to crank up the compiler warning levels
                so string literals may effectively be marked 'const' without
                producing any diagnostics.

                When there are ripple effects with function return type or
                sometimes some other function return type, the decision
                needs to be made on a case-by-case basis. Usually though
                the cost of this sort of refactoring isn't too high, and it
                results in finding defects reasonably often, so mostly using
                'const' for pointer parameters seems like it's a win.
                Naturally there are the occasional exceptions.

                Comment

                • Bryan Donlan

                  #9
                  Re: function (const char *) vs. function (char *)

                  andrew.fabbro@g mail.com wrote:
                  [color=blue]
                  > In a different newsgroup, I was told that a function I'd written that
                  > looked like this:
                  >
                  > void myfunc (char * somestring_ptr)
                  >
                  > should instead be
                  >
                  > void myfunc (const char * somestring_ptr)
                  >
                  > When I asked why, I was told that it facilitated calling it as:
                  >
                  > myfunc ("String");
                  >
                  > instead of
                  >
                  > strcpy (string, "What I want");
                  > myfunc (string);
                  >
                  > However, now that I experiment with it, I find that my original
                  > prototype
                  >
                  > void myfunc (char * somestring_ptr)
                  >
                  > works perfectly well with either invocation.
                  >
                  > So I'm curious why "const char *" would be desirable?
                  >
                  > The only difference I see it makes is that it forbids modification of
                  > the string within the function...of course, you can't modify the
                  > original copy of the string, since C is call-by-value, but I guess
                  > const char * means you can't modify the passed copy in the function
                  > either...perhap s this is just an additional safeguard?[/color]

                  C is pass-by-value, yes, but the value passed is a pointer to the string
                  data. So, for example if you did:

                  void myfunc(char *ptr) {
                  ptr[0] = 'b';
                  }

                  /* ... */
                  char buf[4];
                  strcpy(buf, "foo");
                  myfunc(buf);
                  puts(buf); // prints boo
                  myfunc("foo"); // Undefined behavior; maybe crash, maybe worse

                  With const char *, changing ptr[0] would be forbidden.

                  --
                  λz.λi.i(i((λ n.λm.λz.λi.n z(λq.mqi))((λ n.λz.λi.n(nzi )i)(λz.λi.i(( (λn.λz.λi.n
                  (nzi)i)(λz.λi .i(iz)))zi)))(( λn.λz.λi.n(n zi)i)(λz.λi.i (iz)))zi))

                  Comment

                  Working...