Memory allocation for an initialized character pointer;

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

    Memory allocation for an initialized character pointer;

    Hi all,

    If I have a piece of code something like this

    void main(void)
    {
    char * p1="abcdefghijk lmn";
    ............... ............... ...............

    }

    For p1 and whatever it points to , where is the memory allocated. Is
    it on heap or stack or
    some other common global area. I am assuming it should be either on
    stack or some global area. Unless
    a user does a malloc storage space cannot be allocated on heap is my
    assumption. Can someone
    throw some light on how compilers do this.

    What if the above piece of code is changed to something like

    void main(void)
    {
    char *p1;
    char a[20]="abcdefgh";

    strcpy(p1,a);
    }

    Now where is the space allocated for p1 and whatever it points to
    after strcpy.

    Thanks in advance.

    Regards,
    Ar
  • Keith Thompson

    #2
    Re: Memory allocation for an initialized character pointer;

    arunajob@gmail. com writes:
    If I have a piece of code something like this
    >
    void main(void)
    {
    char * p1="abcdefghijk lmn";
    ............... ............... ...............
    >
    }
    The correct declaration for main is "int main(void)". See the
    comp.lang.c FAQ, <http://www.c-faq.com/>, questions 11.12a, 11.12b,
    11.14a, 11.14b, and 11.15.
    For p1 and whatever it points to , where is the memory allocated. Is
    it on heap or stack or
    some other common global area. I am assuming it should be either on
    stack or some global area. Unless
    a user does a malloc storage space cannot be allocated on heap is my
    assumption. Can someone
    throw some light on how compilers do this.
    Storage for p1 itself (the pointer object) has what the standard calls
    "automatic storage duration". That means it's created on entry to the
    main function, and deallocated on exit from the main function. On a
    typical system, it will be allocated on the "stack", but
    implementations are allowed to use whatever mechanism meets the
    standard's requirements.

    Storage for the string literal, "abcdefghijklmn " plus the terminating
    '\0' character, has "static storage duration". This storage exists
    for the entire lifetime of the program. Again, implementations are
    allowed to use whatever mechanism meets the standard's requirements.
    What if the above piece of code is changed to something like
    >
    void main(void)
    {
    char *p1;
    char a[20]="abcdefgh";
    >
    strcpy(p1,a);
    }
    p1 and a (a pointer object and an array object) have "automatic
    storage duration"; in a typical implementation, they'll be stored on
    the "stack" (but see above). Notionally, the contents of the string
    literal are stored somewhere with static storage duration, but since
    it's used only to initialize a, the compiler doesn't actually need to
    keep it around.

    But the strcpy() call will most likely fail. It attempts to copy 8
    bytes ("abcdefg" plus the trailing '\0') to whatever memory p1 points
    to, but you haven't allocated any memory for p1 to point to. It might
    appear to work correctly, it might terminate your program with an
    error message (if you're lucky), or it might clobber some critical
    piece of memory and cause arbitrarily bad things to happen, limited
    only by whatever safeguards are imposed by your operating system.
    This is what the standard calls "undefined behavior".

    You could allocate memory using malloc():

    p1 = malloc(strlen(a ) + 1);
    if (p1 == NULL) {
    /* malloc failed, handle the error somehow */
    }
    else {
    strcpy(p1, a); /* p1 now points to a copy of the string */
    }

    [...]

    Many questions like this can be answered by checking the comp.lang.c
    FAQ (URL above).

    --
    Keith Thompson (The_Other_Keit h) kst-u@mib.org <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

    Comment

    • jameskuyper@verizon.net

      #3
      Re: Memory allocation for an initialized character pointer;

      aruna...@gmail. com wrote:
      Hi all,
      >
      If I have a piece of code something like this
      >
      void main(void)
      'void' is not a legal return type for main(), though many compilers do
      their users a disservice by allowing it. Change it to int, and add a
      corresponding 'return' statement down below.
      {
      char * p1="abcdefghijk lmn";
      ............... ............... ...............
      >
      }
      >
      For p1 and whatever it points to , where is the memory allocated. Is
      it on heap or stack or
      some other common global area. I am assuming it should be either on
      stack or some global area. Unless
      a user does a malloc storage space cannot be allocated on heap is my
      assumption. Can someone
      throw some light on how compilers do this.
      The memory is statically allocated. The result is roughly equivalent
      to writing

      int main(void)
      {
      static const char some_name[] = {'a', 'b', 'c', 'd', 'e', 'f',
      'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', '\0'};
      char *p1 = (char*)some_nam e;

      The actual location for such static memory is up to your compiler. As
      usual, Twink has given you an answer that might be relevant to your
      particular compiler, or it might be complete nonsense. The only way to
      know for sure is to check your compilers' documentation, which would
      have been a better answer than the one Twink gave you.
      What if the above piece of code is changed to something like
      >
      void main(void)
      {
      char *p1;
      char a[20]="abcdefgh";
      >
      strcpy(p1,a);
      }
      >
      Now where is the space allocated for p1 and whatever it points to
      after strcpy.
      String literals are treated differently when they initialize char*
      pointers than they are when they initialize char arrays. In the first
      case, static memory is allocated for the contents of the string
      literal, and the pointer is initialized with a value that points to
      the first character of the array. It is not safe to attempt to write
      to that array.

      In the second case, the contents of the string literal are used to
      directly initialize the declared array; no separate storage is
      allocated. Whether or not the memory has static storage duration or
      automatic storage duration depends upon the declaration of the array;
      the same is true about whether or not the array is declared as
      'const'.

      In this case, both p1 and a are both allocated as memory with
      automatic storage duration, which usually, but not necessarily, means
      that it is allocated from a hardware stack. You'll need to check your
      compiler's documentation to find out exactly how this is handled.

      Each time a statement block is entered, objects defined in that block
      with automatic storage duration need to be re-initialized. This isn't
      an issue for your program, because it contains only one block which is
      never reentered; the only such objects in your program could be
      handled the same way as static memory, without causing any problems.
      However, in the more general case this means that the information
      needed to re-initialize the object each time the block is entered must
      be stored somewhere else. The standard says nothing about how this
      information is stored, and there are many different ways to do it. For
      small objects, the data might even be stored as part of the
      initialization instructions, rather than in a seperate block of
      memory.

      Now we come to the nasty part. p1 is uninitialized before the call to
      strcpy(). As a result, the behavior of your program is undefined. In
      principle, even attempting to read the value of p1 might make your
      program abort, and there have been real machines where that would have
      happened. In practice, what is likely to happen is that p1 contains a
      bit pattern about which you know nothing, including whether or not it
      represents a valid memory location. That pattern will be interpreted
      as if it did represent a pointer, and that pointer value will be
      passed to strcpy(). strcpy() will attempt to copy the string located
      in 'a' to this unknown memory location. The consequences of doing so
      could be catastrophic; on systems with poor memory protection, like MS/
      DOS, it was actually possible to damage devices with a write to the
      wrong memory location; it was certainly easy to mess up the
      configuration of your computer, requiring at least a reboot. On more
      modern OSs (a category that includes many OSs that predate MS/DOS by
      decades), such code is like to produce a memory segment violation,
      which will halt your program. If it doesn't halt, that means that p1
      happens to point at a memory location that your program actually has
      permission to write to, such as &p1. However, this will be an
      unpredictable part of the memory allocated to your program, which
      stands a good chance of making some other unpredictable part of your
      program fail.

      In short: NEVER use the value of an uninitialized variable; be
      particularly careful about uninitialized pointer variables. You should
      make sure that p1 points at something before you ask strcpy() to copy
      something to the location p1 points at. You should also make sure that
      whatever p1 points at, it is big enough to store the thing that you're
      copying to it.

      Comment

      • s0suk3@gmail.com

        #4
        Re: Memory allocation for an initialized character pointer;

        On Sep 30, 2:46 pm, Keith Thompson <kst-u@mib.orgwrote:
        arunajob@gmail. com writes:
        If I have a piece of code something like this
        >
        void main(void)
        {
           char * p1="abcdefghijk lmn";
            ............... ............... ...............
        >
        }
        >
        The correct declaration for main is "int main(void)".
        But it's not the /only/ correct one. There's also "int main(int, char
        **)", or anything your implementation supports:

        <quote>
        5.1.2.2.1 Program startup

        1 The function called at program startup is named main. The
        implementation declares no prototype for this function. It shall be
        defined with a return type of int and with no parameters:

        int main(void) { /* ... */ }

        or with two parameters (referred to here as argc and argv, though any
        names may be used, as they are local to the function in which they are
        declared):

        int main(int argc, char *argv[]) { /* ... */ }

        or equivalent;9) or in some other implementation-defined manner.

        <end quote>

        Thus, the prototype shown by the OP is also correct.

        Sebastian

        Comment

        • Keith Thompson

          #5
          Re: Memory allocation for an initialized character pointer;

          s0suk3@gmail.co m writes:
          On Sep 30, 2:46 pm, Keith Thompson <kst-u@mib.orgwrote:
          >arunajob@gmail. com writes:
          If I have a piece of code something like this
          >>
          void main(void)
          {
             char * p1="abcdefghijk lmn";
              ............... ............... ...............
          >>
          }
          >>
          >The correct declaration for main is "int main(void)".
          >
          But it's not the /only/ correct one. There's also "int main(int, char
          **)", or anything your implementation supports:
          >
          <quote>
          5.1.2.2.1 Program startup
          [snip]
          or equivalent;9) or in some other implementation-defined manner.
          >
          <end quote>
          >
          Thus, the prototype shown by the OP is also correct.
          That depends on what you mean by "correct". And no, I'm not playing
          word games; it really does depend on what you mean by "correct".

          An implementation is allowed, but not required, to support "void
          main(void)". (In fact, this is covered by the general permission to
          support extensions; the "or in some other implementation-defined
          manner" wording in 5.1.2.2.1 is redundant.)

          So if the OP's particular implementation, for whatever reason,
          supports "void main(void)" -- which means that it must *document* it,
          not just accidentally fail to reject it -- then "void main(void)" is
          arguably correct *for that implementation* . But it's not portable; it
          can be rejected, or can cause undefined behavior, on any
          implementation that doesn't choose to support it. For example, the
          status code returned to the environment when the program terminates is
          normally the int value returned from main(), or passed to exit(). If
          main() doesn't return an int value, what status code does the
          environment see? The standard certainly doesn't say; the
          implementation may or may not document it.

          And there is absolutely no advantage to using "void main(void)" rather
          than "int main(void)". You give up portability for the sake of
          .... what exactly do you gain? Well, you can omit the "return 0;" or
          "exit(EXIT_SUCC ESS);" at the end of main() -- but C99 lets you omit
          that anyway.

          So yes, "void main(void)" can be "correct" in some narrow
          circumstances. Or it can be incorrect.

          But "int main(void)" is unquestionably correct. (Assuming, of course,
          that you're using a C89 or better compiler that recognizes the "void"
          keyword in this context -- but "void main(void)" is certainly no
          better in that case.)

          The above assumes a hosted implementation. In a freestanding
          implementation (very loosely, an embedded system), "int main(void)"
          might not be valid. But it's safe to assume that the OP is using a
          hosted implementation.

          (Cue the trolls whining that the correct declaration of main is the
          only thing we discuss here.)

          --
          Keith Thompson (The_Other_Keit h) kst-u@mib.org <http://www.ghoti.net/~kst>
          Nokia
          "We must do something. This is something. Therefore, we must do this."
          -- Antony Jay and Jonathan Lynn, "Yes Minister"

          Comment

          • vippstar@gmail.com

            #6
            Re: Memory allocation for an initialized character pointer;

            On Sep 30, 11:35 pm, s0s...@gmail.co m wrote:
            On Sep 30, 2:46 pm, Keith Thompson <ks...@mib.orgw rote:
            >
            aruna...@gmail. com writes:
            If I have a piece of code something like this
            >
            void main(void)
            {
            char * p1="abcdefghijk lmn";
            ............... ............... ...............
            >
            }
            >
            The correct declaration for main is "int main(void)".
            >
            But it's not the /only/ correct one. There's also "int main(int, char
            **)", or anything your implementation supports:
            >
            <quote>
            5.1.2.2.1 Program startup
            >
            1 The function called at program startup is named main. The
            implementation declares no prototype for this function. It shall be
            defined with a return type of int and with no parameters:
            >
            int main(void) { /* ... */ }
            >
            or with two parameters (referred to here as argc and argv, though any
            names may be used, as they are local to the function in which they are
            declared):
            >
            int main(int argc, char *argv[]) { /* ... */ }
            >
            or equivalent;9) or in some other implementation-defined manner.
            >
            <end quote>
            >
            Thus, the prototype shown by the OP is also correct.
            It seems correct to you means "compile on some implementations "
            Clearly you need to participate in implementation-specific groups to
            share your implementation specific expertise, because here, it's not
            correct.

            Comment

            • s0suk3@gmail.com

              #7
              Re: Memory allocation for an initialized character pointer;

              On Sep 30, 3:54 pm, Keith Thompson <kst-u@mib.orgwrote:
              s0suk3@gmail.co m writes:
              On Sep 30, 2:46 pm, Keith Thompson <kst-u@mib.orgwrote:
              arunajob@gmail. com writes:
              If I have a piece of code something like this
              >
              void main(void)
              {
                 char * p1="abcdefghijk lmn";
                  ............... ............... ...............
              >
              }
              >
              The correct declaration for main is "int main(void)".
              >
              But it's not the /only/ correct one. There's also "int main(int, char
              **)", or anything your implementation supports:
              >
              <quote>
              5.1.2.2.1 Program startup
              [snip]
              or equivalent;9) or in some other implementation-defined manner.
              >
              <end quote>
              >
              Thus, the prototype shown by the OP is also correct.
              >
              That depends on what you mean by "correct".  And no, I'm not playing
              word games; it really does depend on what you mean by "correct".
              I meant correct in the sense that it's valid according to the
              standard.
              An implementation is allowed, but not required, to support "void
              main(void)".  (In fact, this is covered by the general permission to
              support extensions; the "or in some other implementation-defined
              manner" wording in 5.1.2.2.1 is redundant.)
              But this would be the kind of extension that a compiler wouldn't be
              able to accept in strictly conforming mode, isn't it? By being
              explicitly mentioned in the standard, a compiler can now accept it in
              so-called conforming mode.
              So if the OP's particular implementation, for whatever reason,
              supports "void main(void)" -- which means that it must *document* it,
              not just accidentally fail to reject it -- then "void main(void)" is
              arguably correct *for that implementation* .  But it's not portable; it
              can be rejected, or can cause undefined behavior, on any
              implementation that doesn't choose to support it.
              Of course, "in an implementation-defined manner" means it will be
              different across implementations . Personally I prefer to define it to
              return int, and to omit the return statement. But I think it isn't
              very accurate to say that "void main(void)" is "incorrect" , only
              because it will be rejected by some implementations .
              For example, the
              status code returned to the environment when the program terminates is
              normally the int value returned from main(), or passed to exit(). If
              main() doesn't return an int value, what status code does the
              environment see? The standard certainly doesn't say; the
              implementation may or may not document it.
              Common sense says: 0 (or, more generally, the value that indicates
              "normal" program termination, in case there's some obscure OS where 0
              isn't such a value).

              Sebastian

              Comment

              • Keith Thompson

                #8
                Re: Memory allocation for an initialized character pointer;

                s0suk3@gmail.co m writes:
                On Sep 30, 3:54 pm, Keith Thompson <kst-u@mib.orgwrote:
                >s0suk3@gmail.co m writes:
                On Sep 30, 2:46 pm, Keith Thompson <kst-u@mib.orgwrote:
                >arunajob@gmail. com writes:
                If I have a piece of code something like this
                >>
                void main(void)
                {
                   char * p1="abcdefghijk lmn";
                    ............... ............... ...............
                >>
                }
                >>
                >The correct declaration for main is "int main(void)".
                >>
                But it's not the /only/ correct one. There's also "int main(int, char
                **)", or anything your implementation supports:
                >>
                <quote>
                5.1.2.2.1 Program startup
                >[snip]
                or equivalent;9) or in some other implementation-defined manner.
                >>
                <end quote>
                >>
                Thus, the prototype shown by the OP is also correct.
                >>
                >That depends on what you mean by "correct".  And no, I'm not playing
                >word games; it really does depend on what you mean by "correct".
                >
                I meant correct in the sense that it's valid according to the
                standard.
                Substituting "valid" for "correct" doesn't make it any clearer.

                It's correct, valid, or whatever you want to call it only with respect
                to a specific implementation, and only if that implementation
                explicitly supports it.
                >An implementation is allowed, but not required, to support "void
                >main(void)".  (In fact, this is covered by the general permission to
                >support extensions; the "or in some other implementation-defined
                >manner" wording in 5.1.2.2.1 is redundant.)
                >
                But this would be the kind of extension that a compiler wouldn't be
                able to accept in strictly conforming mode, isn't it? By being
                explicitly mentioned in the standard, a compiler can now accept it in
                so-called conforming mode.
                No. The requirement in 5.1.2.2.1 is not a constraint, which means
                that violating it invokes undefined behavior; no diagnostic is
                required. Since no strictly conforming program can use
                "void main(void)", and no diagnostic is required for it, anything an
                implementation does with it is within the bounds of the standard.

                BTW, "strictly conforming" applies to programs, not to implementations
                or modes. An implementation is conforming or it isn't.
                >So if the OP's particular implementation, for whatever reason,
                >supports "void main(void)" -- which means that it must *document* it,
                >not just accidentally fail to reject it -- then "void main(void)" is
                >arguably correct *for that implementation* .  But it's not portable; it
                >can be rejected, or can cause undefined behavior, on any
                >implementati on that doesn't choose to support it.
                >
                Of course, "in an implementation-defined manner" means it will be
                different across implementations . Personally I prefer to define it to
                return int, and to omit the return statement. But I think it isn't
                very accurate to say that "void main(void)" is "incorrect" , only
                because it will be rejected by some implementations .
                I certainly wouldn't call it "correct".
                >For example, the
                >status code returned to the environment when the program terminates is
                >normally the int value returned from main(), or passed to exit(). If
                >main() doesn't return an int value, what status code does the
                >environment see? The standard certainly doesn't say; the
                >implementati on may or may not document it.
                >
                Common sense says: 0 (or, more generally, the value that indicates
                "normal" program termination, in case there's some obscure OS where 0
                isn't such a value).
                Common sense doesn't necessarily apply. I've used a compiler that
                does the equivalent of "exit(1)" if you fall off the end of main()
                without executing a return statement. This was perfectly valid
                behavior according to the C90 standard (it wasn't a C99 compiler).

                --
                Keith Thompson (The_Other_Keit h) kst-u@mib.org <http://www.ghoti.net/~kst>
                Nokia
                "We must do something. This is something. Therefore, we must do this."
                -- Antony Jay and Jonathan Lynn, "Yes Minister"

                Comment

                • s0suk3@gmail.com

                  #9
                  Re: Memory allocation for an initialized character pointer;

                  On Oct 1, 12:12 am, Keith Thompson <kst-u@mib.orgwrote:
                  s0suk3@gmail.co m writes:
                  On Sep 30, 3:54 pm, Keith Thompson <kst-u@mib.orgwrote:
                  s0suk3@gmail.co m writes:
                  On Sep 30, 2:46 pm, Keith Thompson <kst-u@mib.orgwrote:
                  arunajob@gmail. com writes:
                  If I have a piece of code something like this
                  >
                  void main(void)
                  {
                     char * p1="abcdefghijk lmn";
                      ............... ............... ...............
                  >
                  }
                  >
                  The correct declaration for main is "int main(void)".
                  >
                  But it's not the /only/ correct one. There's also "int main(int, char
                  **)", or anything your implementation supports:
                  >
                  <quote>
                  5.1.2.2.1 Program startup
                  [snip]
                  or equivalent;9) or in some other implementation-defined manner.
                  >
                  <end quote>
                  >
                  Thus, the prototype shown by the OP is also correct.
                  >
                  That depends on what you mean by "correct".  And no, I'm not playing
                  word games; it really does depend on what you mean by "correct".
                  >
                  I meant correct in the sense that it's valid according to the
                  standard.
                  >
                  Substituting "valid" for "correct" doesn't make it any clearer.
                  >
                  It's correct, valid, or whatever you want to call it only with respect
                  to a specific implementation, and only if that implementation
                  explicitly supports it.
                  Yes, but, again, I was talking in regard to the standard, not to any
                  particular implementation.
                  An implementation is allowed, but not required, to support "void
                  main(void)".  (In fact, this is covered by the general permission to
                  support extensions; the "or in some other implementation-defined
                  manner" wording in 5.1.2.2.1 is redundant.)
                  >
                  But this would be the kind of extension that a compiler wouldn't be
                  able to accept in strictly conforming mode, isn't it? By being
                  explicitly mentioned in the standard, a compiler can now accept it in
                  so-called conforming mode.
                  >
                  No.  The requirement in 5.1.2.2.1 is not a constraint, which means
                  that violating it invokes undefined behavior; no diagnostic is
                  required.  Since no strictly conforming program can use
                  "void main(void)", and no diagnostic is required for it, anything an
                  implementation does with it is within the bounds of the standard.
                  What!? I'm not following. The quote I made from the standard mentions
                  three prototype forms for main: "int main(void)", "int main(int, char
                  **)" and "some other implementation-defined manner". Now, "void
                  main(void)" would fall under the third category; am I wrong? What do
                  you mean by saying that a strictly conforming program can't use "void
                  main(void)"?
                  BTW, "strictly conforming" applies to programs, not to implementations
                  or modes.  An implementation is conforming or it isn't.
                  >
                  So if the OP's particular implementation, for whatever reason,
                  supports "void main(void)" -- which means that it must *document* it,
                  not just accidentally fail to reject it -- then "void main(void)" is
                  arguably correct *for that implementation* .  But it's not portable; it
                  can be rejected, or can cause undefined behavior, on any
                  implementation that doesn't choose to support it.
                  >
                  Of course, "in an implementation-defined manner" means it will be
                  different across implementations . Personally I prefer to define it to
                  return int, and to omit the return statement. But I think it isn't
                  very accurate to say that "void main(void)" is "incorrect" , only
                  because it will be rejected by some implementations .
                  >
                  I certainly wouldn't call it "correct".
                  If the standard says it is, why not?

                  Sebastian

                  Comment

                  • Richard Heathfield

                    #10
                    Re: Memory allocation for an initialized character pointer;

                    s0suk3@gmail.co m said:

                    <snip>
                    The quote I made from the standard mentions
                    three prototype forms for main: "int main(void)", "int main(int, char
                    **)" and "some other implementation-defined manner". Now, "void
                    main(void)" would fall under the third category; am I wrong? What do
                    you mean by saying that a strictly conforming program can't use "void
                    main(void)"?
                    Firstly, the Standard does not require any implementation to provide
                    support for *any* entry point other than int main(void), int main(int,
                    char **), and exact equivalents. (The rules for freestanding
                    implementations are even looser, but let's not go there just now.) There
                    is certainly no requirement to provide support for void main(void).

                    Therefore, even if a particular implementation defines a meaning for void
                    main(void), the behaviour of such a program on some *other* (arbitrary)
                    implementation is undefined.

                    Secondly, a strictly conforming program is one that "shall use only those
                    features of the language and library specified in this International
                    Standard.2) It shall not produce output dependent on any unspecified,
                    undefined, or implementation-defined behavior, and shall not exceed any
                    minimum implementation limit."

                    Since void main(void) is not specified by the Standard, and also since it
                    can't be demonstrated that the very use of void main(void) does not
                    produce output dependent on any unspecified, undefined, or
                    implementation-defined behaviour, it cannot be used in a strictly
                    conforming program.
                    Of course, "in an implementation-defined manner" means it will be
                    different across implementations . Personally I prefer to define it to
                    return int, and to omit the return statement. But I think it isn't
                    very accurate to say that "void main(void)" is "incorrect" , only
                    because it will be rejected by some implementations .
                    >>
                    >I certainly wouldn't call it "correct".
                    >
                    If the standard says it is, why not?
                    The Standard doesn't say it's correct. It says that implementations are
                    allowed to define a meaning for it. But implementations are allowed to
                    define a meaning for anything they like - they can even give meaning to
                    Ook! programs if they want. But that doesn't make Ook! programs "correct"
                    in C terms.

                    --
                    Richard Heathfield <http://www.cpax.org.uk >
                    Email: -http://www. +rjh@
                    Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
                    "Usenet is a strange place" - dmr 29 July 1999

                    Comment

                    • s0suk3@gmail.com

                      #11
                      Re: Memory allocation for an initialized character pointer;

                      On Oct 1, 1:05 am, Richard Heathfield <rjh@see.sig.in validwrote:
                      s0suk3@gmail.co m said:
                      >
                      <snip>
                      >
                      The quote I made from the standard mentions
                      three prototype forms for main: "int main(void)", "int main(int, char
                      **)" and "some other implementation-defined manner". Now, "void
                      main(void)" would fall under the third category; am I wrong? What do
                      you mean by saying that a strictly conforming program can't use "void
                      main(void)"?
                      >
                      Firstly, the Standard does not require any implementation to provide
                      support for *any* entry point other than int main(void), int main(int,
                      char **), and exact equivalents. (The rules for freestanding
                      implementations are even looser, but let's not go there just now.) There
                      is certainly no requirement to provide support for void main(void).
                      >
                      Therefore, even if a particular implementation defines a meaning for void
                      main(void), the behaviour of such a program on some *other* (arbitrary)
                      implementation is undefined.
                      So far, the bottom line remains the same: it *is* correct; it simply
                      isn't guaranteed to work on every compiler.
                      Secondly, a strictly conforming program is one that "shall use only those
                      features of the language and library specified in this International
                      Standard.2) It shall not produce output dependent on any unspecified,
                      undefined, or implementation-defined behavior, and shall not exceed any
                      minimum implementation limit."
                      >
                      Since void main(void) is not specified by the Standard, and also since it
                      can't be demonstrated that the very use of void main(void) does not
                      produce output dependent on any unspecified, undefined, or
                      implementation-defined behaviour, it cannot be used in a strictly
                      conforming program.
                      Now that's a shocker. Does that mean that, say, bit-fields in
                      structures can't be used in a strictly conforming program? (Whether
                      bit-fields are stored from right to left or from left to right is
                      implementation-defined.) In fact, does that mean that variables of
                      type int, long, or any type other than char, can't be used in a
                      strictly conforming program because their sizes are also
                      implementation-defined?
                      Of course, "in an implementation-defined manner" means it will be
                      different across implementations . Personally I prefer to define it to
                      return int, and to omit the return statement. But I think it isn't
                      very accurate to say that "void main(void)" is "incorrect" , only
                      because it will be rejected by some implementations .
                      >
                      I certainly wouldn't call it "correct".
                      >
                      If the standard says it is, why not?
                      >
                      The Standard doesn't say it's correct. It says that implementations are
                      allowed to define a meaning for it. But implementations are allowed to
                      define a meaning for anything they like - they can even give meaning to
                      Ook! programs if they want. But that doesn't make Ook! programs "correct"
                      in C terms.
                      But they'd be providing Ook! support as an extension (which would be
                      quite an useful extension, btw!). Accepting void main(void) isn't an
                      extension.

                      Sebastian

                      Comment

                      • raashid bhatt

                        #12
                        Re: Memory allocation for an initialized character pointer;

                        On Oct 1, 12:04 am, aruna...@gmail. com wrote:
                        Hi all,
                        >
                        If I have a piece of code something like this
                        >
                        void main(void)
                        {
                        char * p1="abcdefghijk lmn";
                        ............... ............... ...............
                        >
                        }
                        >
                        For p1 and whatever it points to , where is the memory allocated. Is
                        it on heap or stack or
                        some other common global area. I am assuming it should be either on
                        stack or some global area. Unless
                        a user does a malloc storage space cannot be allocated on heap is my
                        assumption. Can someone
                        throw some light on how compilers do this.
                        >
                        What if the above piece of code is changed to something like
                        >
                        void main(void)
                        {
                        char *p1;
                        char a[20]="abcdefgh";
                        >
                        strcpy(p1,a);
                        >
                        }
                        >
                        Now where is the space allocated for p1 and whatever it points to
                        after strcpy.
                        >
                        Thanks in advance.
                        >
                        Regards,
                        Ar
                        in your first example
                        char *p1 will be allocated on stack not on heap but "abcdefghijklmn "
                        will be stored as global
                        now comming to your second example i am sorry to say your code is
                        wrong ....see

                        as you declare a pointer without initializing it so where is points
                        is dependent on your linker and OS it will generally point to 0 ( that
                        is a null pointer) ....
                        so you cannot copy bytes to it strcpy(p1, a) ; that is wrong

                        right way to do it is

                        char *p1 = NULL;
                        p1 = a;
                        then no need for strcpy();

                        even in this example the pointer will still be allocated on the stack
                        not on heap;

                        Comment

                        • Bart van Ingen Schenau

                          #13
                          Re: Memory allocation for an initialized character pointer;

                          On 1 okt, 09:27, s0s...@gmail.co m wrote:
                          On Oct 1, 1:05 am, Richard Heathfield <r...@see.sig.i nvalidwrote:
                          >
                          >
                          >
                          s0s...@gmail.co m said:
                          >
                          <snip>
                          >
                          The quote I made from the standard mentions
                          three prototype forms for main: "int main(void)", "int main(int, char
                          **)" and "some other implementation-defined manner". Now, "void
                          main(void)" would fall under the third category; am I wrong? What do
                          you mean by saying that a strictly conforming program can't use "void
                          main(void)"?
                          >
                          Firstly, the Standard does not require any implementation to provide
                          support for *any* entry point other than int main(void), int main(int,
                          char **), and exact equivalents. (The rules for freestanding
                          implementations are even looser, but let's not go there just now.) There
                          is certainly no requirement to provide support for void main(void).
                          >
                          Therefore, even if a particular implementation defines a meaning for void
                          main(void), the behaviour of such a program on some *other* (arbitrary)
                          implementation is undefined.
                          >
                          So far, the bottom line remains the same: it *is* correct; it simply
                          isn't guaranteed to work on every compiler.
                          No. The phrase "some other implementation-defined manner" means that
                          void main() is only correct if the implementation documents it as
                          being so.
                          If the implementation does not document void main() as a possible
                          entry point, then using void main() with that implementation results
                          in UB, which means that this use of void main() can not be correct.

                          So, you can"t say without qualification that void main() is correct.
                          You can at most say that it is correct for certain implementations .
                          >
                          Secondly, a strictly conforming program is one that "shall use only those
                          features of the language and library specified in this International
                          Standard.2) It shall not produce output dependent on any unspecified,
                          undefined, or implementation-defined behavior, and shall not exceed any
                          minimum implementation limit."
                          >
                          Since void main(void) is not specified by the Standard, and also since it
                          can't be demonstrated that the very use of void main(void) does not
                          produce output dependent on any unspecified, undefined, or
                          implementation-defined behaviour, it cannot be used in a strictly
                          conforming program.
                          >
                          Now that's a shocker. Does that mean that, say, bit-fields in
                          structures can't be used in a strictly conforming program? (Whether
                          bit-fields are stored from right to left or from left to right is
                          implementation-defined.) In fact, does that mean that variables of
                          type int, long, or any type other than char, can't be used in a
                          strictly conforming program because their sizes are also
                          implementation-defined?
                          No, because you can write programs that don't depend on the
                          implementation defined aspects of bitfields or the integer types.

                          For example, this is a strictly conforming program:
                          <cut>
                          #include <stdio.h>
                          struct bits {
                          int value:4;
                          };
                          int main(void)
                          {
                          struct bits result;
                          int lhs, rhs;

                          lhs = 4;
                          rhs = 3;
                          result.value = lhs + rhs;
                          printf("%d\n", result.value);
                          return 0;
                          }
                          <cut>

                          The program is strictly conforming, because the output does not depend
                          on the choices that an implementation may have made for the
                          unspecified or implementation-defined behaviours or values.
                          >
                          Sebastian
                          Bart v Ingen Schenau

                          Comment

                          • Richard Heathfield

                            #14
                            Re: Memory allocation for an initialized character pointer;

                            Bart van Ingen Schenau said:
                            On 1 okt, 09:27, s0s...@gmail.co m wrote:
                            >On Oct 1, 1:05 am, Richard Heathfield <r...@see.sig.i nvalidwrote:
                            >>
                            >>
                            >>
                            s0s...@gmail.co m said:
                            >>
                            <snip>
                            >>
                            The quote I made from the standard mentions
                            three prototype forms for main: "int main(void)", "int main(int,
                            char **)" and "some other implementation-defined manner". Now, "void
                            main(void)" would fall under the third category; am I wrong? What do
                            you mean by saying that a strictly conforming program can't use
                            "void main(void)"?
                            >>
                            Firstly, the Standard does not require any implementation to provide
                            support for *any* entry point other than int main(void), int main(int,
                            char **), and exact equivalents. (The rules for freestanding
                            implementations are even looser, but let's not go there just now.)
                            There is certainly no requirement to provide support for void
                            main(void).
                            >>
                            Therefore, even if a particular implementation defines a meaning for
                            void main(void), the behaviour of such a program on some *other*
                            (arbitrary) implementation is undefined.
                            >>
                            >So far, the bottom line remains the same: it *is* correct; it simply
                            >isn't guaranteed to work on every compiler.
                            >
                            No. The phrase "some other implementation-defined manner" means that
                            void main() is only correct if the implementation documents it as
                            being so.
                            If the implementation does not document void main() as a possible
                            entry point, then using void main() with that implementation results
                            in UB, which means that this use of void main() can not be correct.
                            >
                            So, you can"t say without qualification that void main() is correct.
                            You can at most say that it is correct for certain implementations .
                            >
                            >>
                            Secondly, a strictly conforming program is one that "shall use only
                            those features of the language and library specified in this
                            International Standard.2) It shall not produce output dependent on any
                            unspecified, undefined, or implementation-defined behavior, and shall
                            not exceed any minimum implementation limit."
                            >>
                            Since void main(void) is not specified by the Standard, and also since
                            it can't be demonstrated that the very use of void main(void) does not
                            produce output dependent on any unspecified, undefined, or
                            implementation-defined behaviour, it cannot be used in a strictly
                            conforming program.
                            >>
                            >Now that's a shocker. Does that mean that, say, bit-fields in
                            >structures can't be used in a strictly conforming program? (Whether
                            >bit-fields are stored from right to left or from left to right is
                            >implementati on-defined.) In fact, does that mean that variables of
                            >type int, long, or any type other than char, can't be used in a
                            >strictly conforming program because their sizes are also
                            >implementati on-defined?
                            >
                            No, because you can write programs that don't depend on the
                            implementation defined aspects of bitfields or the integer types.
                            >
                            For example, this is a strictly conforming program:
                            <cut>
                            #include <stdio.h>
                            struct bits {
                            int value:4;
                            };
                            int main(void)
                            {
                            struct bits result;
                            int lhs, rhs;
                            >
                            lhs = 4;
                            rhs = 3;
                            result.value = lhs + rhs;
                            printf("%d\n", result.value);
                            return 0;
                            }
                            <cut>
                            >
                            The program is strictly conforming,
                            If you change the struct def to:

                            struct bits {
                            signed int value:4;
                            };

                            you don't have to worry about whether passing an unsigned int to printf as
                            a match for %d is an issue or not (and since I can never remember myself
                            whether it is, I find it easier to make things explicitly correct).

                            --
                            Richard Heathfield <http://www.cpax.org.uk >
                            Email: -http://www. +rjh@
                            Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
                            "Usenet is a strange place" - dmr 29 July 1999

                            Comment

                            • Nick Keighley

                              #15
                              Re: Memory allocation for an initialized character pointer;

                              On 1 Oct, 09:44, raashid bhatt <raashidbh...@g mail.comwrote:
                              On Oct 1, 12:04 am, aruna...@gmail. com wrote:
                              If I have a piece of code something like this
                              >
                              void main(void)
                              {
                                 char * p1="abcdefghijk lmn";
                                  ............... ............... ...............
                              }
                              >
                              For p1 and  whatever it points to , where is the memory allocated. Is
                              it on heap or stack or
                              some other common global area. I am assuming it should be either on
                              stack or some global area. Unless
                              a user does a malloc storage space cannot be allocated on heap is my
                              assumption.
                              since The Standard doesn't mention heaps there is no restriction on an
                              implementaion using the heap (or stack) for whatever it pleases. The
                              static variables area could be stack or heap. (on old Macs the heap
                              was on the stack).

                              Can someone
                              throw some light on how compilers do this.
                              they have to allocate a block of memory before program startup.
                              How they do this is the implementors business. It is common
                              to just grab a lump of memory for statis data.

                              What if the above piece of code is changed to something like
                              >
                              void main(void)
                              {
                                  char *p1;
                                  char a[20]="abcdefgh";
                              >
                                  strcpy(p1,a);
                              >
                              }
                              >
                              Now where is the space allocated for p1 and whatever it points to
                              after strcpy.
                              >
                              in your first example
                              char *p1 will be allocated on stack not on heap but "abcdefghijklmn "
                              will be stored as global
                              now comming to your second example i am sorry to say your code is
                              wrong ....see
                              >
                              as you declare a pointer without initializing  it so where is points
                              is dependent on your linker and OS it will generally point to 0 ( that
                              is a null pointer) ....
                              if by "generally" you mean "usually" I don't think this is so.
                              In my experience it contains whatever "random" crap has been
                              left on the stack. Many OSs *don't* clear the memory
                              before dishing it out to processes.
                              so you cannot copy bytes to it strcpy(p1, a) ; that is wrong
                              >
                              right way to do  it is
                              >
                              char *p1 = NULL;
                              initialising it to NULL is not necessary
                              p1 = a;
                              then no need for strcpy();
                              yes, but that may not be what the user wanted. he might
                              want to modify what p points to.

                              even in this example the pointer will still be allocated on the stack
                              not on heap

                              --
                              Nick Keighley

                              Comment

                              Working...