Re: Compiler difference

From: Sam Sungshik Kong (ssk_at_chol.nospam.net)
Date: 08/27/04

  • Next message: Mike Wahler: "Re: Compiler difference"
    Date: Fri, 27 Aug 2004 19:00:21 GMT
    
    

    Make, thanks for your reply.

    >size_t void split(char* in_str, char* out_str[MAX_NUMBER], int* size_t)
    About the style issue, I originally wanted to implement it like you said.
    However, when I checked other examples of array and its size, they tend to
    stick them together.
    So I decided to keep them together.
    I prefer your way though.

    >String literals, by definition are not allowed to be
    >modified. Attempts to do so result in 'undefined behavior'
    The following is also string literal, right?
    char s[] = "one;two;three;four;five;";
    And it can be modified.
    What's the difference between char* s and char s[]?

    >char** t; //caused run time error and changed char* t[MAX_NUMBER]
    > This creates a pointer, but doesn't give it a value (it doesn't
    > point anywhere. Evalutating the value of this pointer will
    > produce more undefined behavior.
    t was meant to be an 'out' parameter.
    That's why I didn't give it a value.
    My wrong understanding...

    Thanks.

    Sam

    "Mike Wahler" <mkwahler@mkwahler.net> wrote in message
    news:p2LXc.213$8d1.46@newsread2.news.pas.earthlink.net...
    >
    > "Sam Sungshik Kong" <ssk@chol.nospam.net> wrote in message
    > news:ObJXc.12342$UL3.12149@newssvr27.news.prodigy.com...
    > > Hello group!
    > >
    > > I am a newbie to C.
    > >
    > > I wrote a string splitting code.
    > > It compiled fine with Borland C++(5.3) and ran ok.
    > > However, the very same code didn't compile with MS C++ for a reason, and
    > > after modification, didn't run well for another reason.
    > >
    > > ----------------Original code----------------
    > >
    > > #include <stdio.h>
    > > #include <string.h>
    > >
    > > #define MAX_NUMBER 20
    > >
    > > void split(char* in_str, char* out_str[MAX_NUMBER], int* length)
    >
    > The following is just a 'style' issue, not part
    > of your problem.
    >
    > Why are you going to the trouble of a pointer
    > argument in order to tell the caller the new
    > 'length'? Why not just have the function return that
    > value? Also, the 'length' should be type 'size_t'.
    >
    > size_t void split(char* in_str, char* out_str[MAX_NUMBER], int* size_t)
    >
    > Then call with e.g.:
    > size_t result = 0
    > result = split(s, t, &count);
    >
    > Your way will work, but imo it's unnecessary.
    >
    > I've addressed the real problems below.
    >
    > > {
    > > char* sep = ";"; //delimiter
    > > int count = 0;
    > >
    > > out_str[count] = strtok(in_str, sep);
    > > while(out_str[count] != NULL)
    > > {
    > > count ++;
    > > out_str[count] = strtok(NULL, sep);
    > > }
    > >
    > > *length = count;
    > > }
    > >
    > >
    > >
    > > int main()
    > > {
    > > char* s = "one;two;three;four;five;"; //later changed into char s[];
    >
    > This creates an unammed array of the characters
    > "one;two;three;four;five;", creates a pointer,
    > and initializes its value with the address of
    > the first character of the array.
    >
    > String literals, by definition are not allowed to be
    > modified. Attempts to do so result in 'undefined behavior'
    > (which can mean anything from 'seems to work', to a
    > horrible crash, or anything else.)
    >
    > > char** t; //caused run time error and changed char* t[MAX_NUMBER]
    >
    > This creates a pointer, but doesn't give it a value (it doesn't
    > point anywhere. Evalutating the value of this pointer will
    > produce more undefined behavior.
    >
    > > int count;
    > >
    > > split(s, t, &count);
    > >
    > > for (int i = 0; i < count; i ++)
    > > {
    > > printf(t[i]);
    > > printf("\n");
    > > }
    > > }
    > >
    > > ----------Anticipated result----------
    > > one
    > > two
    > > three
    > > four
    > > five
    > > ------------------------------------
    >
    > One cannot accurately predict undefined behavior.
    > Equally allowed output of your program (if any) would be
    > "boogity boo!".
    >
    > >
    > > I found out that strtok modifies the original string.
    >
    > Yes, it does.
    >
    > > Borland C++ allowed "char* s" to be modified but MS C++ didn't.
    >
    > The pointer can be validly modifed. What you've pointed it
    > to is not (the string literal). The syntax rules don't
    > prohibit it, but the result is specified as undefined.
    > The compiler was not required (but not prohibited either)
    > to reject the code.
    >
    > > I changed char* s into char s[] and it compiled with MS C++.
    > >
    > > Even after compilation with MS C++, this program caused an exception.
    >
    > Yes, the other problem was still there (using uninitialized
    > object 't'.)
    >
    > > I changed char** t into char* t[MAX_NUMBER] and it became fine.
    >
    > Right. Because now 'strtok()' has somewhere to write to that
    > is 'owned' by your program. Before it did not.
    >
    > > I guess this was my fault.
    >
    > Yup. :-)
    >
    > > But I wonder why the program compiled with Borland C++ didn't cause any
    > > error.
    >
    > Your code had no diagnosable errors, just undefined behavior
    > (which cannot always be diagnosed).
    >
    > Your best protection against such bugs is not to depend upon
    > a compiler to report your mistakes, but to get a very good
    > grasp of the language rules, and of course thoughtfulness
    > and carefulness.
    >
    > -Mike
    >
    >


  • Next message: Mike Wahler: "Re: Compiler difference"

    Relevant Pages

    • Re: pointer and storage
      ... I always thought that where the string literals are stored ... it invokes undefined behavior. ... pointer is unconditionally bad, ... "hello" is not const char *. ...
      (comp.lang.c)
    • Re: double* p=malloc(1) // OK?
      ... The pointer returned by malloc "is suitably aligned ... some gaps in the wording of the standard. ... to an array, where a single object is treated as a one-element array. ... Are the last two lines defined behavior or undefined behavior? ...
      (comp.std.c)
    • Re: What does the standard say about array access wraparound?
      ... Note that the object you've named 'array' is ... *not* an array, it's a pointer. ... so evaluating it will produce undefined behavior. ... and 'len' should be of type 'size_t', not 'int'. ...
      (comp.lang.c)
    • Re: Question related to string functions
      ... is not terminated by '\0' it can show undefined behavior? ... array whose size is specified as exactly the length of the array, ... Character string literals that are adjacent ... not a special case of string literals. ...
      (comp.lang.c)
    • Re: simple question regarding 5.5 of Ritchie & Kernighan
      ... > pointer may subsequently be modified to point elsewhere, ... The standard specifies that string literals (i.e. "..." ... > array of chars in memory terminated with a NULL and this is pointed to ... writes to the array amessage and not the string literal object, ...
      (comp.lang.c)