pointer from integer without a cast

Discussion in 'C Programming' started by Rudra Banerjee, Aug 28, 2012.

  1. Dear friends,
    I am a C novice. I am trying to get the basename of a file(filename) without extension. The problem is much discussed in net, but due to my limited knowledge, I failed to make fruitful use of them, and thought I may use the unix command, as given.

    char myCommand[512];
    // char *basetmp=strrchr(filename,'/')+1;
    sprintf(myCommand,"basename %s .bib",filename);
    char *basefn=system((char *)myCommand);
    printf (basefn);
    variable filename is defined as char*.
    This code is giving warnning:308:18: warning: initialization makes pointer from integer without a cast [enabled by default]
    where line no 308 is "char *basefn=system((char *)myCommand);"

    If anybody kindly show me where I am getting wrong, or better still, a better(and small) method to get the same function without unix command, it will be of huge help.
    Rudra Banerjee, Aug 28, 2012
    #1
    1. Advertising

  2. On Tue, 28 Aug 2012 14:56:50 -0700 (PDT), Rudra Banerjee
    <> wrote:

    >Dear friends,
    >I am a C novice. I am trying to get the basename of a file(filename) without extension. The problem is much discussed in net, but due to my limited knowledge, I failed to make fruitful use of them, and thought I may use the unix command, as given.
    >
    > char myCommand[512];
    >// char *basetmp=strrchr(filename,'/')+1;
    > sprintf(myCommand,"basename %s .bib",filename);
    > char *basefn=system((char *)myCommand);
    > printf (basefn);
    >variable filename is defined as char*.
    >This code is giving warnning:308:18: warning: initialization makes pointer from integer without a cast [enabled by default]
    >where line no 308 is "char *basefn=system((char *)myCommand);"
    >
    >If anybody kindly show me where I am getting wrong, or better still, a better(and small) method to get the same function without unix command, it will be of huge help.


    The C function system() does not return the "output" of the command it
    executes. It returns an implementation-defined "status" which has
    type int. (Most commands return 0 status to indicate success.)

    In this case, the output from basename probably went directly to your
    screen. One way for you to get the output, if your system supports
    redirection (>>), would be to add " >> basename_output_file.txt" to
    your sprintf format string and then open the file and read the output.

    By the way, your cast in the call to system() serves no purpose.
    myCommand is an array of char. In this context, the expression
    myCommand is automatically converted to &myCommand[0] which already
    has type char*.

    --
    Remove del for email
    Barry Schwarz, Aug 28, 2012
    #2
    1. Advertising

  3. Rudra Banerjee

    James Kuyper Guest

    On 08/28/2012 05:56 PM, Rudra Banerjee wrote:
    > Dear friends,
    > I am a C novice. I am trying to get the basename of a file(filename) without extension. The problem is much discussed in net, but due to my limited knowledge, I failed to make fruitful use of them, and thought I may use the unix command, as given.
    >
    > char myCommand[512];
    > // char *basetmp=strrchr(filename,'/')+1;
    > sprintf(myCommand,"basename %s .bib",filename);
    > char *basefn=system((char *)myCommand);
    > printf (basefn);
    > variable filename is defined as char*.
    > This code is giving warnning:308:18: warning: initialization makes pointer from integer without a cast [enabled by default]
    > where line no 308 is "char *basefn=system((char *)myCommand);"
    >
    > If anybody kindly show me where I am getting wrong,


    The value returned by system() is an int. Your code tries to implicitly
    convert that int to a pointer, which is not permitted, hence the warning
    message. Such conversions can only be done explicitly by using a cast.
    Inserting (int) before system() would disable the warning message, but
    would not solve your problem. The value returned by the system() command
    when it is given a non-null pointer argument is an
    implementation-defined status code, so converting it to a pointer is
    pointless, and could cause your program to crash.

    I'm familiar with the basename command as a standard utility available
    on unix-like systems like the ones I use at home and at work. I've not
    idea whether other systems provide a similar command with the same name.
    The rest of this message is specific to my desktop system, and if not
    applicable to your system, should be ignored. If the advice is
    applicable to your system, any questions should be directed to
    comp.programmer.unix, rather than this forum. There are people there who
    can give you better answers than I can about such systems.

    system() returns "-1 on error (e.g. fork() failed), and the return
    status of the command otherwise. This latter return status is in the
    format specified in wait(2)." That's not what you want.

    What you really want is to capture the string that gets printed out by
    the basename command, but capturing that string is a complicated task
    that would start with using popen() rather than system(), and gets
    steadily more complicated from there. I'd recommend someday learning how
    to do that, because someday you might need to, but this isn't that day;
    wait until you no longer call yourself a "novice".

    You're much better off using the basename() function, rather than
    system() and the basename command. Type "man 3 basename" at your command
    line for more information.
    James Kuyper, Aug 28, 2012
    #3
  4. Rudra Banerjee

    Lew Pitcher Guest

    On Tuesday 28 August 2012 17:56, in comp.lang.c, wrote:

    > Dear friends,
    > I am a C novice. I am trying to get the basename of a file(filename)
    > without extension. The problem is much discussed in net, but due to my
    > limited knowledge, I failed to make fruitful use of them, and thought I
    > may use the unix command, as given.
    >
    > char myCommand[512];
    > // char *basetmp=strrchr(filename,'/')+1;
    > sprintf(myCommand,"basename %s .bib",filename);

    [snip
    > If anybody kindly show me where I am getting wrong, or better still, a
    > better(and small) method to get the same function without unix command, it
    > will be of huge help.


    The POSIX standard defines a C function called basename() that, on Unix-like
    platforms, does most of what you want to do. But, as we are discussing your
    problem in comp.lang.c, we'll not discuss POSIX functions; they are best
    left for discussion in a POSIX, Unix, or Linux newsgroup.

    OTOH, if you know the rules for filename (and presumably pathname) creation
    on your platform (like, "paths are names separated by slashes", or "a slash
    at the rightmost end of the name can be ignored"), and the rules for the
    basename utility program (like, the 2nd parameter is a filename suffix),
    *you* can write the equivalent processing in standard C.

    Working from right to left (from end-of-string to start-of-string)
    - delete the trailing slash if present
    - delete the file suffix if present
    - find the leftmost slash, or start of string

    Your filename starts +1 from that leftmost slash (or +0 from the start of
    string), and ends just prior to that file suffix you deleted.
    This is /easily/ coded in C, without any function calls.

    HTH
    --
    Lew Pitcher
    "In Skills, We Trust"
    Lew Pitcher, Aug 29, 2012
    #4
  5. Rudra Banerjee

    Lew Pitcher Guest

    Too quick to post without proofreading

    On Tuesday 28 August 2012 19:03, in comp.lang.c,
    wrote:

    [snip]
    > Working from right to left (from end-of-string to start-of-string)
    > - delete the trailing slash if present
    > - delete the file suffix if present
    > - find the leftmost slash, or start of string


    Gaak! Correction
    - find the RIGHTMOST slash, or start of string

    >

    Your filename starts +1 from that RIGHTMOST slash (or +0 from the start of
    string), and ends just prior to that file suffix you deleted.
    > This is /easily/ coded in C, without any function calls.


    --
    Lew Pitcher
    "In Skills, We Trust"
    Lew Pitcher, Aug 29, 2012
    #5
  6. Rudra Banerjee <> writes:

    > Dear friends, I am a C novice. I am trying to get the basename of a
    > file(filename) without extension. The problem is much discussed in
    > net, but due to my limited knowledge, I failed to make fruitful use of
    > them, and thought I may use the unix command, as given.


    >
    > char myCommand[512];
    > // char *basetmp=strrchr(filename,'/')+1;
    > sprintf(myCommand,"basename %s .bib",filename);
    > char *basefn=system((char *)myCommand);
    > printf (basefn);


    NOTE: that's dangerous! All hell will break loose if the file name
    includes %s for example.

    > variable filename is defined as char*.


    > This code is giving warnning:308:18: warning: initialization makes
    > pointer from integer without a cast [enabled by default] where line no
    > 308 is "char *basefn=system((char *)myCommand);"
    >
    > If anybody kindly show me where I am getting wrong, or better still, a
    > better(and small) method to get the same function without unix
    > command, it will be of huge help.


    For the Unix answer, see if your system has a basename function. To
    find out more about it, ask in comp.unix.programmer.

    There's a C answer as well, because the problem is just one of
    manipulating characters so here is an explanation of a simple way to do
    what you want.

    You are on the right track with strrchr but exactly what will work for
    you depends on what you want to do with the string later and where the
    file name came from to start with.

    The most flexible method will make a copy of the resulting shortened
    file name. The only thing you then need to worry about is freeing the
    storage when you no longer need it.

    Here are the key parts:

    strrchr can find the last / in the name, but it may return NULL if
    there was no / to find:

    const char *basename = strrchr(filename, '/');
    if (basename == NULL)
    basename = filename;
    else basename += 1; // point to after the '/' just found

    strrchr can then also find the . that marks a possible extension.
    Again you need to check if there really is one:

    const char *end = strrchr(basename, '.');
    if (end == NULL)
    end = strrchr(basename, 0); // can't fail

    If you specifically want to remove only ".bib" it's a little bit more
    complicated because you might have a name like "my.bib.file.bib". The
    following would work:

    const char *end = strchr(basename, 0);
    if (strlen(basename) >= 4 && strcmp(end - 4, ".bib") == 0)
    end -= 4;

    Subtracting two pointers into an array (a string is just an array of
    characters) gives you the number of elements between them. To make a
    copy of a part of the string, you can use strndup. It's not standard
    C, but you don't seem to be looking for a fully standard solution:

    return strndup(basename, end - basename);

    To avoid strndup, all you need is malloc to get the storage and memcpy
    to copy the characters:

    char *copy = malloc(end - basename + 1); // +1 for the null we add
    if (copy != NULL) {
    memcpy(copy, basename, end - basename);
    copy[basename - end] = 0;
    }
    return copy;

    The whole thing then needs to be wrapped up into a function for general
    use. Something like:

    char *get_basename(const char *filename)
    {
    ....
    }

    Change the name if you choose the version that only removes a trailing
    ".bib"!

    --
    Ben.
    Ben Bacarisse, Aug 29, 2012
    #6
  7. Rudra Banerjee

    BartC Guest

    Rudra Banerjee" <> wrote in message
    news:...
    > I am a C novice. I am trying to get the basename of a file(filename)
    > without extension. The problem is much discussed in net, but due to my
    > limited knowledge, I failed to make fruitful use of them, and thought I
    > may use the unix command, as given.


    > If anybody kindly show me where I am getting wrong, or better still, a
    > better(and small) method to get the same function without unix command, it
    > will be of huge help.


    I've knocked together some code here. This does a few extra things, I
    believe the functionality you want is in 'ExtractBaseFile()', but as
    written, these are interdependent.

    This code is little peculiar because it uses a 'string slice' type to return
    a result; that is a pointer to a string plus a length, rather than just a
    pointer to C-terminated string. This makes it possible to point into the
    middle of an existing string (and to avoid messing with malloc()). To use
    the result conventionally use the MakeCstring() conversion, or just copy the
    bytes into a char array, and add a zero..

    (I've assumed that filespecs on your machine are like Windows', except with
    no "\" or ":" characters.)

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>

    typedef struct {char* str; int len;}strslice;

    /* ------------------------------------ */
    strslice MakeSlice(char* str,int len){
    strslice s;
    s.str=str;
    s.len=len;
    return s;
    }

    /* ------------------------------------ */
    strslice ExtractPath(char* filespec){
    int i,len;
    char *p,*q;

    len=strlen(filespec);
    p=filespec+len-1; /* point to last char */
    for (i=len; i>=1; --i)
    if (*p--=='/') {
    return MakeSlice(filespec,i);
    }
    return MakeSlice("",0);
    }

    /* ------------------------------------ */
    strslice ExtractFile(char* filespec){
    strslice s;
    int len;

    s=ExtractPath(filespec);
    if (s.len==0) return MakeSlice(filespec,strlen(filespec)); /* No path
    */
    return MakeSlice(s.str+s.len,strlen(filespec)-s.len);
    }

    /* ------------------------------------ */
    strslice ExtractExt(char* filespec,int period){
    /* period=1: return trailing "." (null ext) as "." rather than "" */
    strslice s;
    char *p;
    int i;

    s=ExtractFile(filespec);
    if (s.len==0) return s;
    p=s.str+s.len-1;
    for (i=s.len; i>=1; --i)
    if (*p--=='.')
    if (i==s.len)
    return period?MakeSlice(".",1):MakeSlice("",0);
    else
    return MakeSlice(p+2,s.len-i+1);
    return MakeSlice("",0);
    }

    /* ------------------------------------ */
    strslice ExtractBaseFile(char* filespec){
    strslice f,e;

    f=ExtractFile(filespec);
    if (f.len==0) return f;
    e=ExtractExt(filespec,0);
    f.len-=e.len;
    if (*(f.str+f.len-1)=='.') --f.len;
    return f;
    }

    /* ------------------------------------ */
    char* MakeCstring(strslice s){
    char *p;
    p=malloc(s.len+1);
    if (p==NULL) return NULL;
    if (s.len) memcpy(p,s.str,s.len);
    *(p+s.len)=0;
    return p;
    }

    /* ------------------------------------ */
    int main (void){
    char *teststr="/path1/path2/basefile.ext";
    strslice slice;
    char *newstr;

    printf("Filespec = %s\n",teststr);

    slice=ExtractPath(teststr);
    printf("Path = \"%.*s\"\n",slice.len,slice.str);

    slice=ExtractFile(teststr);
    printf("File = \"%.*s\"\n",slice.len,slice.str);

    slice=ExtractBaseFile(teststr);
    printf("Base = \"%.*s\"\n",slice.len,slice.str);

    slice=ExtractExt(teststr,1);
    printf("Ext = \"%.*s\"\n",slice.len,slice.str);

    newstr=MakeCstring(slice);
    printf("Ext'= \"%s\"\n",newstr);
    }

    --
    Bartc
    BartC, Aug 29, 2012
    #7
  8. "BartC" <> writes:
    <snip>
    > /* ------------------------------------ */
    > strslice ExtractPath(char* filespec){
    > int i,len;
    > char *p,*q;
    >
    > len=strlen(filespec);
    > p=filespec+len-1; /* point to last char */


    This is technically UB when filespec has zero length. You can, I think,
    just drop the -1 and change *p-- to *--p below:

    > for (i=len; i>=1; --i)
    > if (*p--=='/') {
    > return MakeSlice(filespec,i);
    > }
    > return MakeSlice("",0);
    > }


    BTW, is this layout and accident of posting or is it how you like to do
    things?

    <snip>
    --
    Ben.
    Ben Bacarisse, Aug 29, 2012
    #8
  9. Rudra Banerjee

    BartC Guest

    "Ben Bacarisse" <> wrote in message
    news:...
    > "BartC" <> writes:
    > <snip>
    >> /* ------------------------------------ */
    >> strslice ExtractPath(char* filespec){
    >> int i,len;
    >> char *p,*q;
    >>
    >> len=strlen(filespec);
    >> p=filespec+len-1; /* point to last char */

    >
    > This is technically UB when filespec has zero length.


    Just pointing to outside the string, without dereferencing (as that's
    protected by the following loop)? If that's a serious consideration, then
    there might be a couple of places where that could happen and needs a change
    of logic. (The original code this was based on just used indexing.)

    >> for (i=len; i>=1; --i)
    >> if (*p--=='/') {
    >> return MakeSlice(filespec,i);
    >> }
    >> return MakeSlice("",0);
    >> }

    >
    > BTW, is this layout and accident of posting or is it how you like to do
    > things?


    I'd like to say it's how I do it late at night just before I go to bed, but
    no that's my normal layout, in my original post anyway.

    But I see some leading spaces get left out when you try and quote the code,
    which is supposed to look like this when you substitute leading "." with
    spaces:

    strslice ExtractPath(char* filespec){
    int i;

    for (i=strlen(filespec)-1; i>=0; --i)
    ..if (filespec=='/')
    ...return MakeSlice(filespec,i+1);
    return MakeSlice("",0);
    }

    (I've also changed this function to avoid the UB ... and the extraneous
    braces.)

    --
    Bartc
    BartC, Aug 29, 2012
    #9
  10. Rudra Banerjee

    James Kuyper Guest

    On 08/29/2012 06:14 AM, BartC wrote:
    > "Ben Bacarisse" <> wrote in message
    > news:...
    >> "BartC" <> writes:
    >> <snip>
    >>> /* ------------------------------------ */
    >>> strslice ExtractPath(char* filespec){
    >>> int i,len;
    >>> char *p,*q;
    >>>
    >>> len=strlen(filespec);
    >>> p=filespec+len-1; /* point to last char */

    >>
    >> This is technically UB when filespec has zero length.

    >
    > Just pointing to outside the string, without dereferencing (as that's
    > protected by the following loop)?


    Yes. You can increment a pointer one past the end of an array with
    defined behavior, but not two past the end, and you can't decrement it
    to any position before the beginning of the array (6.5.6p8). The
    asymmetry of these rules reflects the fact that some very common loop
    idioms require incrementing past the end of an array, but no common
    idiom requires going past the beginning.

    These idioms became commonplace before the restrictions were imposed, so
    this is not an example of circular logic (e.g.: it was disallowed
    because no one was using it - no one was using it because it wasn't
    allowed).

    <pedantic>Technically, the standard only endorses end_of_array+1 as a
    permitted pointer value. It doesn't cover (end_of_array-1)+2. Some
    people have argued that (end_of_array-1)+2 is necessarily equal to
    end_of_array+1, but to "prove" that identity they assume the associative
    property (a+b)+c == a + (b+c). That property can be proven to be true
    based upon 6.5.6p8 when 'a' is a pointer type, but only for the cases
    where a, a+b, and (a+b)+c all point within the same array; the proof
    cannot be validly extended to include pointers one past the end of the
    array.</pedantic>
    --
    James Kuyper
    James Kuyper, Aug 29, 2012
    #10
  11. James Kuyper <> writes:
    <snip>
    > <pedantic>Technically, the standard only endorses end_of_array+1 as a
    > permitted pointer value. It doesn't cover (end_of_array-1)+2. Some
    > people have argued that (end_of_array-1)+2 is necessarily equal to
    > end_of_array+1, but to "prove" that identity they assume the associative
    > property (a+b)+c == a + (b+c). That property can be proven to be true
    > based upon 6.5.6p8 when 'a' is a pointer type, but only for the cases
    > where a, a+b, and (a+b)+c all point within the same array; the proof
    > cannot be validly extended to include pointers one past the end of the
    > array.</pedantic>


    I'm a bit baffled. I'd get it if you were talking about
    (beginning_of_array-1)+1 but I can't see the problem with
    (end_of_array-1)+2 in general. Are you talking about the specific case
    when the array has one element (so beginning_of_array==end_of_array)?

    Another possibility is that you meant end_of_array+2-1 but one way or
    another I need more explanation to know what you are getting at.

    --
    Ben.
    Ben Bacarisse, Aug 29, 2012
    #11
  12. "BartC" <> writes:
    <snip>
    > But I see some leading spaces get left out when you try and quote the code,
    > which is supposed to look like this when you substitute leading "."
    > with spaces:
    >
    > strslice ExtractPath(char* filespec){
    > int i;
    >
    > for (i=strlen(filespec)-1; i>=0; --i)
    > .if (filespec=='/')
    > ..return MakeSlice(filespec,i+1);
    > return MakeSlice("",0);
    > }


    FYI It was missing in the message I received and was not a function of
    my quoting the code, so some space presumably did get lost in posting.

    <snip>
    --
    Ben.
    Ben Bacarisse, Aug 29, 2012
    #12
  13. Kenneth Brody <> writes:

    > On 8/28/2012 7:14 PM, Ben Bacarisse wrote:
    >> Rudra Banerjee <> writes:
    >>
    >>> Dear friends, I am a C novice. I am trying to get the basename of a
    >>> file(filename) without extension. The problem is much discussed in
    >>> net, but due to my limited knowledge, I failed to make fruitful use of
    >>> them, and thought I may use the unix command, as given.

    >>
    >>>
    >>> char myCommand[512];
    >>> // char *basetmp=strrchr(filename,'/')+1;
    >>> sprintf(myCommand,"basename %s .bib",filename);
    >>> char *basefn=system((char *)myCommand);
    >>> printf (basefn);

    >>
    >> NOTE: that's dangerous! All hell will break loose if the file name
    >> includes %s for example.

    >
    > Actually, given that:
    >
    > 1 - This appears to be for *nix.
    > 2 - system() will most likely return zero because the command will
    > probably succeed.
    > 3 - On most systems, the conversion of (int)0 to (char *) will
    > probably result in NULL.
    >
    > The filename is pretty much irrelevant, since printf(NULL) will
    > probably always crash.
    >
    > Also, what if the filename contains a space, or semicolon, or one of
    > numerous other characters, which will cause system(myCommand) to fail?


    Yes, you are right, but by the time I posted the whole system() thing
    had been declared a non-stater. I wanted to point out a new and as yet
    unremarked on problem. But I should have snipped much more to make that
    clear.

    Any reply to a use of system based on a plain sprintf of a file name
    should probably include this link:

    http://xkcd.com/327/

    or at least a remark that '/; rm -rf ~; echo' is my favourite test file.

    <snip>
    --
    Ben.
    Ben Bacarisse, Aug 29, 2012
    #13
  14. Rudra Banerjee

    James Kuyper Guest

    On 08/29/2012 04:16 PM, Ben Bacarisse wrote:
    > James Kuyper <> writes:
    > <snip>
    >> <pedantic>Technically, the standard only endorses end_of_array+1 as a
    >> permitted pointer value. It doesn't cover (end_of_array-1)+2. Some
    >> people have argued that (end_of_array-1)+2 is necessarily equal to
    >> end_of_array+1, but to "prove" that identity they assume the associative
    >> property (a+b)+c == a + (b+c). That property can be proven to be true
    >> based upon 6.5.6p8 when 'a' is a pointer type, but only for the cases
    >> where a, a+b, and (a+b)+c all point within the same array; the proof
    >> cannot be validly extended to include pointers one past the end of the
    >> array.</pedantic>

    >
    > I'm a bit baffled. I'd get it if you were talking about
    > (beginning_of_array-1)+1 but I can't see the problem with
    > (end_of_array-1)+2 in general. Are you talking about the specific case
    > when the array has one element (so beginning_of_array==end_of_array)?
    >
    > Another possibility is that you meant end_of_array+2-1 but one way or
    > another I need more explanation to know what you are getting at.


    To provide a context for the following paragraphs:

    int array[10];
    int *end_of_array = array+9;
    int *P;
    int a, b;

    The C standard says "if the expression P points to the last
    element of an array object, the expression (P)+1 points one past the
    last element of the array object," (6.5.6p8). This statement only
    applies to additions of 1, and only to pointers that point "to the last
    element of an array object. It doesn't apply to adding any number other
    than 1, nor does it apply to adding an integer to a pointer that points
    at any location other than the last element of an array object.

    6.5.6p8 also defines the result of adding an integer to a pointer in a
    more general case:
    > If the pointer operand points to an element of
    > an array object, and the array is large enough, the result points to an element offset from
    > the original element such that the difference of the subscripts of the resulting and original
    > array elements equals the integer expression. In other words, if the expression P points to
    > the i-th element of an array object, the expressions (P)+N (equivalently, N+(P)) and
    > (P)-N (where N has the value n) point to, respectively, the i+n-th and i−n-th elements of
    > the array object, provided they exist.


    Note, however, that this definition applies to P+a if and only if p and
    p+a both point within the same array. Because of that limitation, while
    it is possible to use that definition to prove that (P+a)+b == P +
    (a+b), the validity of that identity is limited to situations where P,
    P+a, and (P+a)+b all point within the array. In particular, when P ==
    end_of_array, (P-1)+2 has no meaning defined by the standard. Therefore,
    that identity can't be used to conclude that (end_of_array-1)+2 is
    equivalent to end_of_array + 1.

    It's also not possible to combine these two definitions to cover that
    case. Try it and see. Keep in mind that can't simply assume that the
    associative property applies - that's precisely the point I'm asking you
    to prove. Associativity certainly applies to addition of ordinary
    integers, and it applies (with exceptions for overflow) to C integers,
    and it applies to the addition of C pointers and C integers as long as
    the pointers stay within the corresponding array. I'm asking you to
    formally prove that the associativity can be extended past the end of
    the array.

    I consider this a defect in the standard, not a statement of how C
    actually works, nor of how it should work. I think the definition of the
    way a pointer one past the end of an array can be created should be
    expanded to cover (array+8)+2 and (array+7)+3, and not just (array+9)+1.
    People who are in a position to get the wording corrected don't agree
    with me.
    James Kuyper, Aug 29, 2012
    #14
  15. Rudra Banerjee

    BartC Guest

    "Ben Bacarisse" <> wrote in message
    news:...
    > "BartC" <> writes:
    > <snip>
    >> But I see some leading spaces get left out when you try and quote the
    >> code,
    >> which is supposed to look like this when you substitute leading "."
    >> with spaces:


    > FYI It was missing in the message I received and was not a function of
    > my quoting the code, so some space presumably did get lost in posting.


    That's odd. The spaces are there when I look at the post using Windows Mail.
    I also had a quick look via Googlegroups, and the spaces were there too (on
    both new and old versions).

    --
    Bartc
    BartC, Aug 29, 2012
    #15
  16. James Kuyper <> writes:

    > On 08/29/2012 04:16 PM, Ben Bacarisse wrote:
    >> James Kuyper <> writes:
    >> <snip>
    >>> <pedantic>Technically, the standard only endorses end_of_array+1 as a
    >>> permitted pointer value. It doesn't cover (end_of_array-1)+2. Some
    >>> people have argued that (end_of_array-1)+2 is necessarily equal to
    >>> end_of_array+1, but to "prove" that identity they assume the associative
    >>> property (a+b)+c == a + (b+c). That property can be proven to be true
    >>> based upon 6.5.6p8 when 'a' is a pointer type, but only for the cases
    >>> where a, a+b, and (a+b)+c all point within the same array; the proof
    >>> cannot be validly extended to include pointers one past the end of the
    >>> array.</pedantic>

    >>
    >> I'm a bit baffled. I'd get it if you were talking about
    >> (beginning_of_array-1)+1 but I can't see the problem with
    >> (end_of_array-1)+2 in general. Are you talking about the specific case
    >> when the array has one element (so beginning_of_array==end_of_array)?
    >>
    >> Another possibility is that you meant end_of_array+2-1 but one way or
    >> another I need more explanation to know what you are getting at.

    >
    > To provide a context for the following paragraphs:
    >
    > int array[10];
    > int *end_of_array = array+9;
    > int *P;
    > int a, b;
    >
    > The C standard says "if the expression P points to the last
    > element of an array object, the expression (P)+1 points one past the
    > last element of the array object," (6.5.6p8). This statement only
    > applies to additions of 1, and only to pointers that point "to the last
    > element of an array object. It doesn't apply to adding any number other
    > than 1, nor does it apply to adding an integer to a pointer that points
    > at any location other than the last element of an array object.


    I see. I did not think you were being that picky. Your example is, to
    my mind, rather too specific to highlight your objection. Unless I am
    still misunderstanding you, array+10 is not permitted either (by your
    reading of the standard) because the "one past" permission applies only
    to adding one to a pointer already at the end.

    Similarly, if we already have a "one past" pointer, Q, evaluating Q-2 is
    (again by your reading) undefined because the permission in 6.5.6 p8
    relates only to (Q)-1, yes?

    Actually, re-reading your remark, I think you obscured your point
    slightly by saying "the standard only endorses end_of_array+1 as a
    permitted pointer value". That's true by any reading. What you are
    complaining about is that is endorses only (P)+1 as an expression that
    can yield this special value.

    <snip>
    > I consider this a defect in the standard, not a statement of how C
    > actually works, nor of how it should work. I think the definition of the
    > way a pointer one past the end of an array can be created should be
    > expanded to cover (array+8)+2 and (array+7)+3, and not just (array+9)+1.
    > People who are in a position to get the wording corrected don't agree
    > with me.


    I don't think there's much scope for confusion. I read the key phrase
    of 6.5.6 p8 as illustrative of how to form this pointer, not as the only
    way, but maybe people have been led astray by this wording.

    --
    Ben.
    Ben Bacarisse, Aug 29, 2012
    #16
  17. James Kuyper <> writes:
    > On 08/29/2012 06:14 AM, BartC wrote:
    >> "Ben Bacarisse" <> wrote in message
    >> news:...
    >>> "BartC" <> writes:

    [...]
    >>>> p=filespec+len-1; /* point to last char */
    >>>
    >>> This is technically UB when filespec has zero length.

    >>
    >> Just pointing to outside the string, without dereferencing (as that's
    >> protected by the following loop)?

    >
    > Yes. You can increment a pointer one past the end of an array with
    > defined behavior, but not two past the end, and you can't decrement it
    > to any position before the beginning of the array (6.5.6p8). The
    > asymmetry of these rules reflects the fact that some very common loop
    > idioms require incrementing past the end of an array, but no common
    > idiom requires going past the beginning.

    [...]

    It also reflects the fact that, if you have an array of large
    elements, a pointer one past the end of the array only requires an
    addressable location one byte past the end of the array, whereas
    a pointer one element before the beginning of the array requires
    an addressable location `sizeof (element_type)` bytes outside the
    array object.

    This isn't likely to matter much for systems with monolithic address
    schemes (you probably won't have an array object allocated close to
    the lower bound of the address space), but it can matter a great
    deal for segmented memory systems, where an array might well be
    allocated at the very beginning of a segment. The C standard is
    carefully written to cater to such systems.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Will write code for food.
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Aug 29, 2012
    #17
  18. Rudra Banerjee

    James Kuyper Guest

    On 08/29/2012 06:22 PM, Ben Bacarisse wrote:
    ....
    > Similarly, if we already have a "one past" pointer, Q, evaluating Q-2 is
    > (again by your reading) undefined because the permission in 6.5.6 p8
    > relates only to (Q)-1, yes?


    Correct. The problem applies in both directions.

    > I don't think there's much scope for confusion. I read the key phrase
    > of 6.5.6 p8 as illustrative of how to form this pointer, not as the only
    > way, but maybe people have been led astray by this wording.


    I don't think many people have been led astray by this wording; I think
    most people have interpreted it as intended, not as written. As written,
    it's not a special-case illustration of a general method for creating a
    pointer one past the end of an array. Rather, it provides the only
    method mentioned anywhere in the standard for creating such pointers,
    and contains nothing to suggest that the method can be generalized
    (other than the fact that we all "know" it can be generalized).
    James Kuyper, Aug 29, 2012
    #18
  19. Kenneth Brody <> writes:
    [...]
    > Also, what if the filename contains a space, or semicolon, or one of
    > numerous other characters, which will cause system(myCommand) to fail?


    Or what if the file name is something like "rm -rf $HOME", which could
    cause system(myCommand) to succeed with disastrous results?

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Will write code for food.
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Aug 29, 2012
    #19
  20. "BartC" <> writes:

    > "Ben Bacarisse" <> wrote in message
    > news:...
    >> "BartC" <> writes:
    >> <snip>
    >>> But I see some leading spaces get left out when you try and quote
    >>> the code,
    >>> which is supposed to look like this when you substitute leading "."
    >>> with spaces:

    >
    >> FYI It was missing in the message I received and was not a function of
    >> my quoting the code, so some space presumably did get lost in posting.

    >
    > That's odd. The spaces are there when I look at the post using Windows
    > Mail. I also had a quick look via Googlegroups, and the spaces were
    > there too (on both new and old versions).


    I checked. They are there and not there! In the literal text of the
    message they are present, but you've posted with format=flowed and
    a leading single space has a special meaning in f=f text. I suspect
    your mailer should have added a space to all the lines carrying code so
    they all get one removed.

    For the moment I'll trust that my news reader is showing me the right
    thing and the GG is not, though I am no expert on how f=f works.

    --
    Ben.
    Ben Bacarisse, Aug 29, 2012
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Rocke Robertson
    Replies:
    14
    Views:
    12,963
    Dan Pop
    Oct 2, 2003
  2. Markus Dehmann
    Replies:
    14
    Views:
    911
    Irrwahn Grausewitz
    Jun 28, 2004
  3. Dawn Minnis
    Replies:
    4
    Views:
    1,509
    Dawn Minnis
    Feb 20, 2005
  4. Replies:
    2
    Views:
    1,210
    Martin Ambuhl
    Apr 1, 2005
  5. Juggernaut
    Replies:
    10
    Views:
    1,574
    CBFalconer
    Apr 9, 2005
Loading...

Share This Page