SIZEOF_NULLCHAR



  • #define SIZEOF_NULLCHAR 1



  •  $implied_facepalm



  • So, TRWTF is it should be called NUL and not NULL ?



  •  Can you paste some code of where this is actually used, or is just a random #define someone threw in ?



  • @Daid said:

    #define SIZEOF_NULLCHAR 1

    #define SIZEOF_NULLCHAR sizeof('\0')


  • Discourse touched me in a no-no place

    @Carnildo said:

    @Daid said:
    #define SIZEOF_NULLCHAR 1

    #define SIZEOF_NULLCHAR sizeof('\0')

    Um...

     

    [@pjhxps /tmp]# cat c.c
    #define X sizeof('\0')
    #include <stdio.h>
    int main(){
    printf("%d\n", X);
    }

    [@pjhxps /tmp]# cat cpp.cpp
    #define X sizeof('\0')
    #include <stdio.h>
    int main(){
    printf("%d\n", X);
    }

    [@pjhxps /tmp]# make -B c cpp
    cc c.c -o c
    g++ cpp.cpp -o cpp
    [@pjhxps /tmp]# ./c
    4
    [@pjhxps /tmp]# ./cpp
    1
    [@pjhxps /tmp]#



  • @Daid said:

    #define SIZEOF_NULLCHAR 1

    Without the context of the system or its usage its impossible to say if this a WTF or not.

    You can speculate all you want and create scenarios where the definition appears to break down, but at best that is just pure mental masturbation



  • @PJH said:

    [@pjhxps /tmp]# ./c
    4

    Why?



  • @derula said:

    @PJH said:
    [@pjhxps /tmp]# ./c
    4

    Why?

     

    Because in C, character constants have type int :)



  • @Ilya Ehrenburg said:

    @derula said:
    @PJH said:
    [@pjhxps /tmp]# ./c
    4
    Why?
     Because in C, character constants have type int :)

    Awesome. So you can type 'c' + 5? ... that looks like PHP.



  • @derula said:

    Awesome. So you can type 'c' + 5? ... that looks like PHP.
     

    'c' + 5 works in a lot of languages. But C is the only one I know that has the types char and int where character constants haven't the type char.



  • @Ilya Ehrenburg said:

    'c' + 5 works in a lot of languages. But C is the only one I know that has the types char and int where character constants haven't the type char.

    Somehow I'm glad I never had to learn C.

    Yet. shiver



  • @derula said:

    @Ilya Ehrenburg said:
    @derula said:
    @PJH said:
    [@pjhxps /tmp]# ./c
    4
    Why?
     Because in C, character constants have type int :)

    Awesome. So you can type 'c' + 5?

    You sure can... you can even write 

        if ('c' + 5 == "c" + 5)
    {
    printf ("double awesome!\n");
    }

    But you probably shouldn't.



  • @derula said:

    @Ilya Ehrenburg said:
    @derula said:
    @PJH said:
    [@pjhxps /tmp]# ./c
    4
    Why?
     Because in C, character constants have type int :)

    Awesome. So you can type 'c' + 5? ... that looks like PHP.

    You can do that even in C++, since char is just a (small) integer type. Assuming the platform uses ASCII or some other similar character set, the result will be equal to 'h', or 104.



  • @OzPeter said:

    @Daid said:
    #define SIZEOF_NULLCHAR 1

    Without the context of the system or its usage its impossible to say if this a WTF or not.

    My guess is it's used like this:

    dst = malloc(strlen(src)+SIZEOF_NULLCHAR);

    You know, just in case someone decides to change the C language so that the string terminator takes more than one byte. Of course, if you're working on something retarded like win32's wide character functions which use UTF-16¹, it already does. But then again, strlen doesn't work with UTF-16.

    ¹At least I think it's UTF-16 these days, in ancient times it was UCS-2 (i.e. no support for surrogates)



  •  @derula said:

    Somehow I'm glad I never had to learn C.Yet. *shiver*

    It gets even more fun when you start using multi-character integers, such as:

    int  a = 'help';

    which will be stored in memory depending on the byte ordering of the system (eg. writing that variable to a file may be written as 'pleh'). 


  • Discourse touched me in a no-no place

    @Mole said:

     @derula said:

    Somehow I'm glad I never had to learn C.Yet. *shiver*

    It gets even more fun when you start using multi-character integers, such as:

    int  a = 'help';

    which will be stored in memory depending on the byte ordering of the system

    Or not at all

     

    [nsb@pjhxps-/tmp]#cat c.c
    #define X sizeof('help')
    #include <stdio.h>
    int main(){
            printf("%d\n", X);
    }
    

    [nsb@pjhxps-/tmp]#make c
    cc c.c -o c
    c.c:4:17: warning: multi-character character constant

     



  • @DaveK said:

    @derula said:
    @Ilya Ehrenburg said:
    @derula said:
    @PJH said:
    [@pjhxps /tmp]# ./c
    4
    Why?
     Because in C, character constants have type int :)
    Awesome. So you can type 'c' + 5?
    You sure can... you can even write
        if ('c' + 5 == "c" + 5)
    {
    printf ("double awesome!\n");
    }

    But you probably shouldn't.

    Wait. Would that condition be ('c' + (5 == "c") + 5) = ('c' + 0 + 5) "=" TRUE? At least that's what my operator precedence sensors detect.



  • @PJH said:

    @Mole said:

     @derula said:

    Somehow I'm glad I never had to learn C.Yet. shiver

    It gets even more fun when you start using multi-character integers, such as:

    int  a = 'help';

    which will be stored in memory depending on the byte ordering of the system

    Or not at all

     

    [nsb@pjhxps-/tmp]#cat c.c
    #define X sizeof('help')
    #include <stdio.h>
    int main(){
    printf("%d\n", X);
    }

    [nsb@pjhxps-/tmp]#make c
    cc c.c -o c
    c.c:4:17: warning: multi-character character constant

    Yes it will, that's only a warning:

    tdb@marmot ~/prog$ cat foo.c
    #include <stdio.h>
    int main()
    {
            int a = 'help';
            printf("%08X %.4s\n", a, (char *)&a);
    }
    tdb@marmot ~/prog$ gcc foo.c -o foo
    foo.c:4:10: warning: multi-character character constant
    tdb@marmot ~/prog$ ./foo
    68656C70 pleh
    

    So why does the compiler give a warning then? Because the value of a multi-character constant is implementation-defined. The compiler could store 0xDEADBEEF to a and still comply with the standard.



  • @Ilya Ehrenburg said:

    @derula said:

    Awesome. So you can type 'c' + 5? ... that looks like PHP.
     

    'c' + 5 works in a lot of languages. But C is the only one I know that has the types char and int where character constants haven't the type char.

     

    On the good old C64 computer, you could write

    PRINT 5+"c"+-5

    ... and that would crash the Basic interpreter, hard :D



  • It was used once:



    iServicenameLength = (unsigned char)strlen(prLoc->rObject_Application_Record[iServiceNr].acServerName) + SIZEOF_NULLCHAR;



    (the string is send over network and is NUL terminated and prefixed with the length for some reason)



    There was also a:

    #define BYTESIZE 0x8u

    But that one was not used.



    Embedded system btw, running linux, used to run on vxWorks. Strings are only 7bits ascii.



  • @derula said:

    At least that's what my operator precedence sensors detect.
     

    No language I know of has == higher than +. The manuals agree for C++, C# and JS.

    I hope you haven't written any critical code based upon a mistaken idea of precedence. :)



  • @derula said:

    @DaveK said:
    @derula said:
    @Ilya Ehrenburg said:
    @derula said:
    @PJH said:
    [@pjhxps /tmp]# ./c
    4
    Why?
     Because in C, character constants have type int :)
    Awesome. So you can type 'c' + 5?
    You sure can... you can even write

        if ('c' + 5 == "c" + 5)
    {
    printf ("double awesome!\n");
    }


    But you probably shouldn't.

    Wait. Would that condition be ('c' + (5 == "c") + 5) = ('c' + 0 + 5) "=" TRUE? At least that's what my operator precedence sensors detect.

    Damage control reports you're suffering a pretty severe sensor malfunction, captain!

    (Also you can't necessarily even assume that the code and data doesn't occupy low memory, so ("c" == 5) might even be true.  Won't happen on most standard desktop systems, but could quite possibly happen on an embedded device.)



  • @dhromed said:

    @derula said:
    At least that's what my operator precedence sensors detect.

    No language I know of has == higher than +. The manuals agree for C++, C# and JS.

    I hope you haven't written any critical code based upon a mistaken idea of precedence. :)

    I think I was confused. Or, tired. Or both.



  • @derula said:

    @dhromed said:
    @derula said:
    At least that's what my operator precedence sensors detect.

    No language I know of has == higher than +. The manuals agree for C++, C# and JS.

    I hope you haven't written any critical code based upon a mistaken idea of precedence. :)

    I think I was confused. Or, tired. Or both.

    Heh, that's what I sometimes call drunk too!

     



  • @Daid said:

    It was used once:



    iServicenameLength = (unsigned char)strlen(prLoc->rObject_Application_Record[iServiceNr].acServerName) + SIZEOF_NULLCHAR;



    (the string is send over network and is NUL terminated and prefixed with the length for some reason)



    Well, I know of one that that's using such format... MudOS.
    [url=http://www.intermud.org/specs/mudmode.html]http://www.intermud.org/specs/mudmode.html[/url]



  • @tdb said:

    Yes it will, that's only a warning:

    tdb@marmot ~/prog$ cat foo.c
    #include <stdio.h>
    int main()
    {
            int a = 'help';
            printf("%08X %.4s\n", a, (char *)&a);
    }
    tdb@marmot ~/prog$ gcc foo.c -o foo
    foo.c:4:10: warning: multi-character character constant
    tdb@marmot ~/prog$ ./foo
    68656C70 pleh
    

    So why does the compiler give a warning then? Because the value of a multi-character constant is implementation-defined. The compiler could store 0xDEADBEEF to a and still comply with the standard.

    But only if it documents that it does so.


  • @Daid said:

    (the string is send over network and is NUL terminated and prefixed with the length for some reason)

    There are reasons for having both nul-termination and a length prefix. When you're receiving data from network, it's useful to know beforehand how much data to expect. A length prefix allows you to read the (fixed size) prefix first and then read the exact right amount of data. On the other hand, having the string nul-terminated as well makes it easy to use it for things like strcat and printf straight from the receive buffer without needing to copy it to another buffer first and add the termination.



  • Why copy to another buffer? Since you know the length already, you could allocate SIZEOF_NULLCHAR extra and place the null character there yourself (before or after) without having to use another buffer or wasting a byte everytime you store a string. 

    I'm suprised by the number of people who use multi-character constants in binary files. Eg. "int a = 'OBJS'; fwrite (&a, 4, 1, fp);" and then being confused when "fread(&b,4,1,fp); if (a==b) {}" doesn't work on a different platform. They are usually the same people that expect sizeof(struct) to be the same on all compilers and so write and read those directly too. 



  • @DaveK said:

    You sure can... you can even write 
        if ('c' + 5 == "c" + 5)
    {
    printf ("double awesome!\n");
    }

    But you probably shouldn't.

     

    OK, I'll take the explaining part then, since there seems to be some confusion. The reason you shouldn't do this is that it will most probably not do what you intended, since 'c'+5 is an integer constant with value 'h' (or 0x68), and "c"+5 is a pointer to a memory location five characters beyond the place where the string "c" begins. In C, since integers and pointers are interchangeable, it will compile and run just fine.




  •  Not on all compilers. Some will complain that you need to cast "C" (basically, a char *) into an integer before it'll compile.

    So you'll need to do:

    if ('c' + 5 == (int)"c" + 5)
        {
            printf ("double awesome!\n");
        }

    If you actually do that however, your just slightly retarded, as the compiler is trying to help you out and your kicking it in the face :-)



  • @Mole said:

    Why copy to another buffer? Since you know the length already, you could allocate SIZEOF_NULLCHAR extra and place the null character there yourself (before or after) without having to use another buffer or wasting a byte everytime you store a string.

    Why are you allocating more memory if not to copy?



  • @Lingerance said:

    Why are you allocating more memory if not to copy?
     

    Your copy routines may depend on the fact that there is normally a null terminator (for example, debug output, window control updates). 

    Instead of copying to another buffer to add the null as suggested above, or rewriting your window handling code, you could add the null to the receive buffer. 




  • @Mole said:

    I'm suprised by the number of people who use multi-character constants in binary files. Eg. "int a = 'OBJS'; fwrite (&a, 4, 1, fp);" and then being confused when "fread(&b,4,1,fp); if (a==b) {}" doesn't work on a different platform. They are usually the same people that expect sizeof(struct) to be the same on all compilers and so write and read those directly too. 

    They're probably coming from a Macintosh background, where these "four-character codes" are a standard way of tagging a data object, and the system ABI defines how multi-character constants behave.


Log in to reply