locked
One more thing... about char* and char[] ? RRS feed

  • Question

  • Hello,

    Ther's one more thing I was wondering. Consider two simple function prototypes:

    1)     void f1(char* c);

    and

    2)    void f1(char c[16]);

    and here consider the calling functions for the two prototypes:

    1)   f1("abc");

    and

    2)  f1("abc");

    The two calling statements are the same for both prototypes. My question is, what is the advantage of using the prototype #2 vs #1 asides for the fact that the user can see that he can pass 15 chars + a presumed '\0' char max!

     In summary, when to use #1 prototype and when to use #2 prototype?

    r

    Wednesday, July 11, 2012 3:48 AM

Answers

  • On 7/11/2012 10:31 AM, roberto wrote:

    Okay so you would of expected something like this:

    void f1(const char* s);

    But suppose it is important that the user not make 's' longer than 16.

    Mention it in the documentation, verify it in the function body, report an error if this precondition is violated. There's no way to get the compiler to enforce it at compile time, so if enforcement is important, it will have to happen at run time.

    How would one know that 16 chars is the maximum length just by looking at a prototype which consists of a simple const char pointer ?

    One wouldn't. That's what comments and documentation are for.

    Also making 's' const in f1's prototype, then once in f1(), I would not be allowed to truncate the string down to 16

    You can't do this anyway, if you want it to be possible for the caller to pass string literals. Modifying a string literal exhibits undefined behavior. MSVC in particular puts string literals into a read-only memory segment, so an attempt to modify one triggers access violation right away.

    So, before I go on a code modification ramp-page, is it so wrong to do this:

    void f1(char c[16]);

    then I call...

    f1("abc");    // At least here I am aware from looking at the prototype that I should not go over 16 chars!!

    Technically, the compiler would accept this code. From readability standpoint, I personally would find such a prototype highly misleading.


    Igor Tandetnik

    • Marked as answer by Elegentin Xie Wednesday, July 18, 2012 4:04 AM
    Wednesday, July 11, 2012 3:53 PM
  • Your mindset is getting in the way of your verbal accuracy.

    You never pass an array to a function.  No matter how hard you try, you end up with a pointer being passed by value.

    If you want to concentrate exclusively on the one dimensional case, then it makes no difference if you code the parameter as
         char x[16]
    or
         char x[]
    or
         char *x
    If you think the last is better, by all means use it.  The compiler doesn't care.  (And for what it's worth, the people who defined the language agree with you since that is what they used for functions like strcpy.)

    But we just finished a previous thread of yours that involved two dinensional arrays.  Which do find easier to work with and more descriptive for people writing functions to call your function?
         char x[][5]
    or
         char x[5][5]
    or
         char (*x)[5]

    And let's not forget the frequent new user mistake of attempting to use
         char **x
    in this case which we know will not work.

    The bottom line is your discussion is completely about style and, in the absence of a corporate standard, I say do what makes the most sense to you.

    • Marked as answer by Elegentin Xie Wednesday, July 18, 2012 4:04 AM
    Wednesday, July 11, 2012 10:33 PM

All replies

  • roberto wrote:

    Ther's one more thing I was wondering. Consider two simple function  prototypes:

    1) void f1(char* c);

    and

    2) void f1(char c[16]);

    There is no difference, as far as the compiler is concerned. These two  prototypes are semantically equivalent. For a human reader, the second  version is probably clearer, assuming the function does in fact expect  an array of 16 characters.

    and here consider the calling functions for the two prototypes:

    1) f1("abc");

    and

    2) f1("abc");

    The call appears to violate the function's contract. The prototype leads  one to believe that the function expects a pointer to a modifiable array  of at least 16 characters. But the caller passes a read-only array of 4  characters. If this is indeed supposed to be a valid call, then the  prototype is misleading. I would have expected something like

    void f1(const char* s);


    Igor Tandetnik

    Wednesday, July 11, 2012 4:13 AM
  • you can also check the following for more deatil

    http://www.cs.bu.edu/teaching/cpp/string/array-vs-ptr/


    Thanks and Regards Selvam http://www15.brinkster.com/selvamselvam/

    Wednesday, July 11, 2012 5:13 AM
  • There is nothing in either prototype to indicate that the pointer f1 receives points to a string.  Even with the second form, it is possible for the array to contain 16 non-nul characters.  If the object pointed to must be a valid string, then that needs to be documented.  There is no way to do that with just syntax.

    And while the syntax of the second form may inded describe the intent, it does not provide a way for the compiler to enforce it.  As your sample code shows, the compiler does not attempt to determine if the actual argument is shorter than, equal to, or longer than the parameter.

    Wednesday, July 11, 2012 5:19 AM
  • Hello guys,

    Okay so you would of expected something like this:

    void f1(const char* s);

    But suppose it is important that the user not make 's' longer than 16.

    For ex, the string cannot be larger than this:

    f1("abcdefghijklmno");  // + '\0'

    How would one know that 16 chars is the maximum length just by looking at a prototype which consists of a simple const char pointer ?

    The reason I am saying this is that usually these types of functions in my project such as f1(), does logic  on the presumption that 's' is not greater than 16!!!!!

    Also making 's' const in f1's prototype, then once in f1(), I would not be allowed to truncate the string down to 16 if there would be a need to unless I reassign the pointer and go from there.

    So, before I go on a code modification ramp-page, is it so wrong to do this:

    void f1(char c[16]);

    then I call...

    f1("abc");    // At least here I am aware from looking at the prototype that I should not go over 16 chars!!

    While "const char *s" works out well for strcpy, strcpy really doesn't care about the lenght of the string as it can handle way more that 16 chars... but it's not always like that... as we can see by f1().

    By the way, selvam, nice article but they are pretty much saying that we can use either or.

    Thanks to all.

    r

    Wednesday, July 11, 2012 2:31 PM
  • On 7/11/2012 10:31 AM, roberto wrote:

    Okay so you would of expected something like this:

    void f1(const char* s);

    But suppose it is important that the user not make 's' longer than 16.

    Mention it in the documentation, verify it in the function body, report an error if this precondition is violated. There's no way to get the compiler to enforce it at compile time, so if enforcement is important, it will have to happen at run time.

    How would one know that 16 chars is the maximum length just by looking at a prototype which consists of a simple const char pointer ?

    One wouldn't. That's what comments and documentation are for.

    Also making 's' const in f1's prototype, then once in f1(), I would not be allowed to truncate the string down to 16

    You can't do this anyway, if you want it to be possible for the caller to pass string literals. Modifying a string literal exhibits undefined behavior. MSVC in particular puts string literals into a read-only memory segment, so an attempt to modify one triggers access violation right away.

    So, before I go on a code modification ramp-page, is it so wrong to do this:

    void f1(char c[16]);

    then I call...

    f1("abc");    // At least here I am aware from looking at the prototype that I should not go over 16 chars!!

    Technically, the compiler would accept this code. From readability standpoint, I personally would find such a prototype highly misleading.


    Igor Tandetnik

    • Marked as answer by Elegentin Xie Wednesday, July 18, 2012 4:04 AM
    Wednesday, July 11, 2012 3:53 PM
  • It would be just as misleading if one does this I guess:

    f1(char* ar){...}

    main(){

    char x[2];

    f1(x);

    }

    So the rule of thumb is if we pass an array then show it as an array parameter. If we want to pass a string literal or pointer to char, then show it as a char* parameter.

    thanks for your help

    r

    Wednesday, July 11, 2012 6:42 PM
  • What part of any of the responses would lead you to such a condusion?  How many functions are able to control what the calling function passes them?  What happens when you write a function expecting an array and later in the devlopement process one of the calling functions builds an array dynamically by calling malloc?

    The C code tells the compiler (and eventually the computer) what to do.  The documentation tells the user what to do.  Both parts are necessary.

    Wednesday, July 11, 2012 7:06 PM
  • >>>What part of any of the responses would lead you to...

    I don't see what you are saying. All I am saying is often I have my arrays in my structs... like this:

    (code not tested... so please tolerate any syntax errors)

    =======================================

    struct myStruct{char x[16];} ms;

    void f1(char* s){bla bla ..... ;  strncpy(ms.x, s, 16));  .....   bla bla;....}

    main(){

    void f1("abcd");

    }

    =========================================

    So when would I ever need to pass in an array like this, it is rare we do this no? :

    f1(char* ar){...}

    main(){

    char x[2] = {"'abc"};

    f1(x);

    }

    You know, you have put yourself in my shoes here a little, I am using both ways but without any specific reason... meaning I have functions that take in a "char* s" and I have functions that take in "char s[16]" and don't really see what's the use to use the "char s[16]" way!!! This what I am trying to explain.

    Now Igor gave me some direction where he says that the prototype should reflect exactly what you will pass in as he critisized the following sample:

    =========================

    void f1(char c[16]);

    then I call...

    f1("abc");

    =========================

    Which I tend to agree with him and I think you do also... so we all agree!!!! So again, my pet peave in all of this is when the heck am I ever going to need to do this:

    =========================

    void f1(char theT[16]){ bla bla bla;}

    then...

    main(){

    char t[16] = {"blabala"};
    f1(t);

    }

    =========================

    Do you see what I mean... for character strings I will never need to use the passing an array to a function way!!!!

    Anyways... I will do what I always do... code it so that it works!

    r

    Wednesday, July 11, 2012 10:10 PM
  • Your mindset is getting in the way of your verbal accuracy.

    You never pass an array to a function.  No matter how hard you try, you end up with a pointer being passed by value.

    If you want to concentrate exclusively on the one dimensional case, then it makes no difference if you code the parameter as
         char x[16]
    or
         char x[]
    or
         char *x
    If you think the last is better, by all means use it.  The compiler doesn't care.  (And for what it's worth, the people who defined the language agree with you since that is what they used for functions like strcpy.)

    But we just finished a previous thread of yours that involved two dinensional arrays.  Which do find easier to work with and more descriptive for people writing functions to call your function?
         char x[][5]
    or
         char x[5][5]
    or
         char (*x)[5]

    And let's not forget the frequent new user mistake of attempting to use
         char **x
    in this case which we know will not work.

    The bottom line is your discussion is completely about style and, in the absence of a corporate standard, I say do what makes the most sense to you.

    • Marked as answer by Elegentin Xie Wednesday, July 18, 2012 4:04 AM
    Wednesday, July 11, 2012 10:33 PM
  • >>>Your mindset is getting in the way of your verbal accuracy.

    >>>You never pass an array to a function.  No matter how hard you try, you end up with a pointer being passed by >>>value.

    Yes!

    r

    Thursday, July 12, 2012 10:51 PM