Is ((char **) &var_name); a cast to char array giving existing pointer to var_name?

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • Rizladonovich
    New Member
    • Sep 2010
    • 13

    Is ((char **) &var_name); a cast to char array giving existing pointer to var_name?

    I am currently reading/learning c. I often like to look at code while I read, - to see more practical use then often are feasible in educational books.

    I am looking at some code from wget.

    Code extracted from wget.
    Code:
    /* file: mswindows.c */
    void
    windows_main (char **exec_name)
    {
      char *p;
    
      /* Remove .EXE from filename if it has one.  */
      *exec_name = xstrdup (*exec_name);
      p = strrchr (*exec_name, '.');
      if (p)
        *p = '\0';
    }
    Code:
    /* file: main.c */
    
    const char *exec_name;
    
    int
    main (int argc, char **argv)
    {
      /* Construct the name of the executable, without the directory part.  */
      exec_name = strrchr (argv[0], PATH_SEPARATOR);
      if (!exec_name)
        exec_name = argv[0];
      else
        ++exec_name;
    
    #ifdef WINDOWS
      /* Drop extension (typically .EXE) from executable filename. */
      windows_main ((char **) &exec_name);
    #endif
    
    ...
    My question goes to what is happening around the call on windows_main from within main, file main.c.

    As i understand it it goes something like this:
    main:
    1. An unchangeable pointer of type char is made by const char *exec_name
    2. ((char **) &exec_name) - this confuses me. Is it making a new char array with address pointing to address of pointer exec_name, or is it some sort of cast?
    3. What about the fact that exec_name is a const? Wouldn't this prohibit change of exec_name?

    windows_main:
    1. windows_main takes a char array as argument.
    2. since exec_name is a const, a editable copy is made by xstrdup, but can this point to same location as the const?
    3. the pointer p is given the address of last dot ('.') in exec_name by strrchr
    4. if p has index higher then 0, the value at that index is given '\0', thus terminating the string exec_name at that position.


    ... this is mighty probable confusing to read... :/


    Code for xstrdup:

    Code:
    void
    xalloc_die (void)
    {
      error (exit_failure, 0, "%s", _("memory exhausted"));
    
      /* The `noreturn' cannot be given to error, since it may return if
         its first argument is 0.  To help compilers understand the
         xalloc_die does not return, call abort.  Also, the abort is a
         safety feature if exit_failure is 0 (which shouldn't happen).  */
      abort ();
    }
    
    /* Allocate N bytes of memory dynamically, with error checking.  */
    
    void *
    xmalloc (size_t n)
    {
      void *p = malloc (n);
      if (!p && n != 0)
        xalloc_die ();
      return p;
    }
    
    /* Clone an object P of size S, with error checking.  There's no need
       for xnmemdup (P, N, S), since xmemdup (P, N * S) works without any
       need for an arithmetic overflow check.  */
    
    void *
    xmemdup (void const *p, size_t s)
    {
      return memcpy (xmalloc (s), p, s);
    }
    
    /* Clone STRING.  */
    
    char *
    xstrdup (char const *string)
    {
      return xmemdup (string, strlen (string) + 1);
    }
    Last edited by Rizladonovich; Sep 19 '10, 04:30 AM. Reason: added code for xstrdup, changed title
  • newb16
    Contributor
    • Jul 2008
    • 687

    #2
    >An unchangeable pointer of type char is made by const char *exec_name

    No. Unchangeable pointer would be "char *const exec_name", and it could't be assigned by exec_name = strrchr (argv[0], PATH_SEPARATOR) ; Here it is a pointer to unchangeable string. So in order to pass it to windows_main (that actually changes the string) one need to remove constness by bruteforce C way.
    I't not clear to me why is it not declared as "char *exec_name;"

    This may work without cast - returning a new string from xmemdup by assigning to char* const temporary variable.

    Code:
    void windows_main(const char ** exec_name)
    {
      char* mutable_string = (char*)xmemdup(*exec_name);
      // alter new string
      mutable_string[1]=0;
      // now return it and promise that it's immutable
      char* const foo(mutable_string);
      *exec_name = foo;
    }
     ...
     windows_main (&exec_name);

    Comment

    • Rizladonovich
      New Member
      • Sep 2010
      • 13

      #3
      Thank you for reply.

      Then unchangeable pointer is out of the way :)
      In other words a const character pointer are defined, and as soon as it is initialized by exec_name = strrchr (argv[0], PATH_SEPARATOR) ; the result is a constant character array (null terminated string)

      So the "((char **) &exec_name); " is a cast then?

      My test:
      Code:
      #include <stdio.h>
      #include <stdlib.h>
      
      const char *k;
      
      void
      test (char **x)
      {
          printf("*x = %p, &x = %p, x = %p, str = %s, **x = %c\n", *x, &x, x, *x, **x);
      
          **x = 'F';
      }
      
      int
      main (int argc, char **argv)
      {
      
          k = argv[0];
          printf("*k = %c, &k = %p, k = %p, str = %s\n", *k, &k, k, k);
          test((char **) &k);
          printf("*k = %c, &k = %p, k = %p, str = %s\n", *k, &k, k, k);
          return 0;
      }
      Result in

      Code:
      >tool
      *k = t, &k = 004050DC, k = 003E3EA9, str = tool
      *x = 003E3EA9, &x = 0022FF30, x = 004050DC, str = tool, **x = t
      *k = F, &k = 004050DC, k = 003E3EA9, str = Fool
      So somehow k becomes editable by casting it. But I am still not sure how I would express what is happening. What I find weird is that the cast is done on an address.
      Last edited by Rizladonovich; Sep 19 '10, 09:02 PM. Reason: some re phrasing

      Comment

      • newb16
        Contributor
        • Jul 2008
        • 687

        #4
        Yes, cast is done on the address - it's the address that is passed to the function, and it is cast. But the only constness is changed is the constness of 'char', not pointers. Was - pointer to pointer to const char, become - pointer to pointer to char. In both cases, pointers can be changed, but the char itself can't.
        Code:
        const char **x;
        x=0; //ok
        *x=0; //ok
        **x=0; //error;

        Comment

        • Rizladonovich
          New Member
          • Sep 2010
          • 13

          #5
          Thank you :)

          Comment

          Working...