sizeof and strlen()

Discussion in 'C Programming' started by Bill Cunningham, May 7, 2010.

  1. Does strlen() not return it's size_t if the data is uninitialized ? And
    sizeof does it work with initialized and uninitialized data?

    For example,

    ssize_t recv(int s, void *buf, size_t len, int flags);

    char buf[1024];

    recv(sock,buf,strlen(buf),0);

    ^
    notice this parameter of the function returns size_t. Would it help if I
    used char buf[1024]={0}; ?

    Bill
     
    Bill Cunningham, May 7, 2010
    #1
    1. Advertising

  2. Bill Cunningham

    Tom St Denis Guest

    On May 7, 2:22 pm, "Bill Cunningham" <> wrote:
    >     Does strlen() not return it's size_t  if the data is uninitialized ? And
    > sizeof does it work with initialized and uninitialized data?
    >
    >     For example,
    >
    > ssize_t recv(int s, void *buf, size_t len, int flags);
    >
    >     char buf[1024];
    >
    > recv(sock,buf,strlen(buf),0);
    >
    >                          ^
    > notice this parameter of the function returns size_t. Would it help if I
    > used char buf[1024]={0}; ?


    I think what it is you found a bug in glibc and should report it right
    away to the maintainers. This is clearly a very severe issue.

    Tom
     
    Tom St Denis, May 7, 2010
    #2
    1. Advertising

  3. Tom St Denis wrote:

    > I think what it is you found a bug in glibc and should report it right
    > away to the maintainers. This is clearly a very severe issue.


    Very funny.

    B
     
    Bill Cunningham, May 7, 2010
    #3
  4. Bill Cunningham

    Lew Pitcher Guest

    On May 7, 2010 14:22, in comp.lang.c, lid wrote:

    > Does strlen() not return it's size_t if the data is uninitialized ?


    strlen() always returns a size_t value, whether argument points at an
    initialized area or not.

    strlen() accepts a pointer to a character array which contains a string in C
    format (terminated with a '\0' (0) character), and returns the length of
    that string. strlen() does *not* return the length of an arbitrary
    character buffer.

    If the pointer you give as the argument to strlen() points to character
    array, initialized with a string, strlen() will return a count of the
    number of significant characters in the string. Technically, it returns a
    count of characters between the start of the string (the pointer's value)
    and the first '\0' (0) character.

    If the pointer you give as the argument to strlen() points to character
    array that is *not* initialized with a string, the results of strlen() are
    unpredictable and likely incorrect. This is because there is no guarantee
    that the character array pointed to contains the sentinal '\0' (0)
    character in /any/ position.

    If the pointer you give as the argument to strlen() points to an
    uninitialized array, the results of strlen() are unpredictable and likely
    incorrect. This is because there is no guarantee that the character array
    pointed to contains the sentinal '\0' (0) character in /any/ position.

    > And
    > sizeof does it work with initialized and uninitialized data?


    sizeof evaluates to the size (in characters) of it's argument. It works
    whether the argument is initialized or not.


    strlen() and sizeof are two different facilities, with two different
    purposes. Please don't confuse them.


    >
    > For example,
    >
    > ssize_t recv(int s, void *buf, size_t len, int flags);
    >
    > char buf[1024];
    >
    > recv(sock,buf,strlen(buf),0);
    >
    > ^
    > notice this parameter of the function returns size_t.


    So?

    > Would it help if I
    > used char buf[1024]={0}; ?


    No, it wouldn't.

    Bill, you still have a fundamental misunderstanding about strlen() and
    sizeof, and about function arguments for specific functions.

    As I pointed out above, strlen() and sizeof are two different facilities,
    with two different purposes.

    sizeof is evaluated once, when you compile your program.
    sizeof evaluates to the size of it's argument, in characters
    sizeof is handy when you want to substitute, at compile time, a value that
    represents the fixed length of an object.

    strlen() is evaluated, possibly many times, when you run your program.
    strlen() counts the number of char elements between the start of an array
    and the first '\0' (0) byte in the array. This count does not have to
    relate /at all/ to the size of the array.
    strlen() is handy when you want to know how big a C string is.

    To illustrate the differences, I'll use a code fragment.....

    First, let's allocate a character array object and initialize it
    with a string

    char buf[1024] = "My buffer";

    Notice that the character array object (<buf>) is 1024 characters long,
    and that it contains a string ("My buffer") which is 10 characters long,
    including the terminating '\0'.

    Let's also allocate a couple of size_t objects:

    size_t bufSizeof,
    bufStrlen;

    Now, let's put some values into thes two size_t objects:

    bufSizeof = sizeof buf;
    bufStrlen = strlen(buf);

    If we look at these two values, we see that
    - bufSizeof is set to 1024, representing the total number of characters
    allocated to buf, and
    - bufStrlen is set to 9, representing the 9 significant characters of the
    string "My buffer", stored in buf

    Follow me so far?

    So we have strlen() to find out how big a *string* is, and sizeof to find
    out how big an *object* is.

    Now, on to your recv() function call.....

    Using your prototype for recv()

    ssize_t recv(int s, void *buf, size_t len, int flags);

    and the relevant documentation (recv() is outside of ISO C, and it's
    documentation is found elsewhere), we find that the argument <len>
    specifies the length (in characters) of the buffer <buf>. Further, we find
    that recv() will, if successful, place no more than <len> characters of new
    data into <buf>.

    You have an object
    char buf[1024];
    and want recv() to put data into that object. You need to tell recv() /how
    much/ data to put into <buf>. The *most* you can ask recv() to put into
    <buf> is (sizeof buf). You can ask for less, of course, but strlen() is not
    an appropriate function (in this example) to determine /how much/ data
    recv() should put in <buf>, because your argument to strlen() *doesn't
    contain a string*.

    To make it simple, until you become more familiar with C, POSIX, sockets,
    and all those other areas of programming that you are exploring, you ALWAYS
    want

    char buf[1024];

    recv(sock,buf,sizeof buf,0);


    HTH
    --
    Lew Pitcher
    Master Codewright & JOAT-in-training | Registered Linux User #112576
    Me: http://pitcher.digitalfreehold.ca/ | Just Linux: http://justlinux.ca/
    ---------- Slackware - Because I know what I'm doing. ------
     
    Lew Pitcher, May 7, 2010
    #4
  5. "Bill Cunningham" <> writes:
    > Does strlen() not return it's size_t if the data is uninitialized ? And
    > sizeof does it work with initialized and uninitialized data?
    >
    > For example,
    >
    > ssize_t recv(int s, void *buf, size_t len, int flags);
    >
    > char buf[1024];
    >
    > recv(sock,buf,strlen(buf),0);
    >
    > ^
    > notice this parameter of the function returns size_t. Would it help if I
    > used char buf[1024]={0}; ?


    A string is a '\0'-terminated sequence of characters. Are you
    working with strings here? No. Then why would you even consider
    using strlen()?

    --
    Keith Thompson (The_Other_Keith) <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"
     
    Keith Thompson, May 7, 2010
    #5
  6. Keith Thompson wrote:

    > A string is a '\0'-terminated sequence of characters. Are you
    > working with strings here? No. Then why would you even consider
    > using strlen()?


    Then I've been reading some really bad code lately. This was not my idea
    to use strlen but the code I was reading used it. Should one use numbers
    such as simply 1024 as int not char* and I put +1 to my code too for the \0.
    I don't know why the author used strlen unless it was because of the size_t.

    Bill
     
    Bill Cunningham, May 7, 2010
    #6
  7. "Bill Cunningham" <> wrote in message
    news:4be479d6$0$12425$...

    > Then I've been reading some really bad code lately. This was not my
    > idea to use strlen but the code I was reading used it. Should one use
    > numbers such as simply 1024 as int not char* and I put +1 to my code too
    > for the \0. I don't know why the author used strlen unless it was because
    > of the size_t.


    I can't find out where I was reading this but this is a page I've been
    getting alot from-

    http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html#sendrecv
     
    Bill Cunningham, May 7, 2010
    #7
  8. Bill Cunningham

    jacob navia Guest

    Bill Cunningham a écrit :
    > "Bill Cunningham" <> wrote in message
    > news:4be479d6$0$12425$...
    >
    >> Then I've been reading some really bad code lately. This was not my
    >> idea to use strlen but the code I was reading used it. Should one use
    >> numbers such as simply 1024 as int not char* and I put +1 to my code too
    >> for the \0. I don't know why the author used strlen unless it was because
    >> of the size_t.

    >
    > I can't find out where I was reading this but this is a page I've been
    > getting alot from-
    >
    > http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html#sendrecv
    >
    >

    This is not true. NOWHERE in that code strlen is used with recv or
    recvfrom. They always use sizeof. The problem is that you can't read
    apparently.
     
    jacob navia, May 7, 2010
    #8
  9. Bill Cunningham

    Lew Pitcher Guest

    On May 7, 2010 16:40, in comp.lang.c, lid wrote:

    >
    > "Bill Cunningham" <> wrote in message
    > news:4be479d6$0$12425$...
    >
    >> Then I've been reading some really bad code lately. This was not my
    >> idea to use strlen but the code I was reading used it. Should one use
    >> numbers such as simply 1024 as int not char* and I put +1 to my code too
    >> for the \0. I don't know why the author used strlen unless it was because
    >> of the size_t.

    >
    > I can't find out where I was reading this but this is a page I've been
    > getting alot from-
    >
    > http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html#sendrecv


    A search through that page shows that /nowhere/ in the code or explanations
    does Beej indicate to use strlen() to set the length on the recv() call. In
    fact, Beej either explicitly sets the length (one or two examples) or uses
    sizeof to specify the length in those recv() calls.

    However, Beej /does/ use strlen() at least once, in an example of the
    *send()* call. And, there, it makes sense, as his example wants to send()
    only the significant characters of a string, and not the entire contents of
    the character array that the string sits in.

    Are you certain that you haven't confused the examples of the send() call
    with the examples of the recv() call?

    --
    Lew Pitcher
    Master Codewright & JOAT-in-training | Registered Linux User #112576
    Me: http://pitcher.digitalfreehold.ca/ | Just Linux: http://justlinux.ca/
    ---------- Slackware - Because I know what I'm doing. ------
     
    Lew Pitcher, May 7, 2010
    #9
  10. Lew Pitcher wrote:

    > A search through that page shows that /nowhere/ in the code or
    > explanations does Beej indicate to use strlen() to set the length on
    > the recv() call. In fact, Beej either explicitly sets the length (one
    > or two examples) or uses sizeof to specify the length in those recv()
    > calls.
    >
    > However, Beej /does/ use strlen() at least once, in an example of the
    > *send()* call. And, there, it makes sense, as his example wants to
    > send() only the significant characters of a string, and not the
    > entire contents of the character array that the string sits in.
    >
    > Are you certain that you haven't confused the examples of the send()
    > call with the examples of the recv() call?


    It is quite possible and probable that I have confused send() and recv()
    parameters. There is no other website I draw more on than his so I would say
    I confused recv() for send(). My apologizes. I will read more carefully and
    watch my quoting other's work.

    Bill
     
    Bill Cunningham, May 7, 2010
    #10
  11. "Bill Cunningham" <> writes:
    > Keith Thompson wrote:
    >> A string is a '\0'-terminated sequence of characters. Are you
    >> working with strings here? No. Then why would you even consider
    >> using strlen()?

    >
    > Then I've been reading some really bad code lately. This was not my idea
    > to use strlen but the code I was reading used it. Should one use numbers
    > such as simply 1024 as int not char* and I put +1 to my code too for the \0.
    > I don't know why the author used strlen unless it was because of the size_t.


    No, you've just been failing to understand the code you're reading.

    The author used strlen because he wanted to compute the length *of a
    string*. He didn't use it "because of the size_t"; he used it because
    it was the correct tool for the job.

    Choose which function or operator to use on the basis of what it does
    and whether that meets your requirement, not just on the basis of what
    type it returns.

    Don't guess.

    --
    Keith Thompson (The_Other_Keith) <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"
     
    Keith Thompson, May 7, 2010
    #11
  12. Lew Pitcher wrote:

    > Are you certain that you haven't confused the examples of the send()
    > call with the examples of the recv() call?


    Right where you cut and pasted I noticed something I don't quite
    understand.

    Beej says:
    int send(int sockfd, const void *msg, int len, int flags);
    sockfd is the socket descriptor you want to send data to (whether it's the
    one returned by socket() or the one you got with accept().) msg is a pointer
    to the data you want to send, and len is the length of that data in bytes.
    Just set flags to 0. (See the send() man page for more information
    concerning flags.)

    Some sample code might be:

    char *msg = "Beej was here!";
    int len, bytes_sent;
    ..
    ..
    ..
    len = strlen(msg);
    bytes_sent = send(sockfd, msg, len, 0);
    ..
    ..
    end quote.len has been declared an int and Beej has strlen passing value to
    it.But strlen returns a size_t. That's the thing I don't understand about
    send().Bill
     
    Bill Cunningham, May 7, 2010
    #12
  13. Keith Thompson wrote:

    > No, you've just been failing to understand the code you're reading.
    >
    > The author used strlen because he wanted to compute the length *of a
    > string*. He didn't use it "because of the size_t"; he used it because
    > it was the correct tool for the job.


    I see.

    > Choose which function or operator to use on the basis of what it does
    > and whether that meets your requirement, not just on the basis of what
    > type it returns.
    >
    > Don't guess.


    This turns upside down some of my beliefs about functions and return
    types. BTW I am still using quote-fix and I'm hoping the quoting is better.

    Bill
     
    Bill Cunningham, May 7, 2010
    #13
  14. "Bill Cunningham" <> writes:
    > Keith Thompson wrote:
    >> No, you've just been failing to understand the code you're reading.
    >>
    >> The author used strlen because he wanted to compute the length *of a
    >> string*. He didn't use it "because of the size_t"; he used it because
    >> it was the correct tool for the job.

    >
    > I see.
    >
    >> Choose which function or operator to use on the basis of what it does
    >> and whether that meets your requirement, not just on the basis of what
    >> type it returns.
    >>
    >> Don't guess.

    >
    > This turns upside down some of my beliefs about functions and return
    > types. BTW I am still using quote-fix and I'm hoping the quoting is better.


    I'm having trouble figuring out what those beliefs might have been. Did
    you think that you could look *only* at what type a function returns and
    decide that it's the right thing? If you were writing mathematical
    software, how would you decide whether to use sin() or sqrt()?

    Please note that I wrote "not *JUST* on the basis of what type it
    reuturns".

    --
    Keith Thompson (The_Other_Keith) <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"
     
    Keith Thompson, May 7, 2010
    #14
  15. "Bill Cunningham" <> writes:
    [...]
    > Beej says:
    > int send(int sockfd, const void *msg, int len, int flags);
    > sockfd is the socket descriptor you want to send data to (whether it's the
    > one returned by socket() or the one you got with accept().) msg is a pointer
    > to the data you want to send, and len is the length of that data in bytes.
    > Just set flags to 0. (See the send() man page for more information
    > concerning flags.)
    >
    > Some sample code might be:
    >
    > char *msg = "Beej was here!";
    > int len, bytes_sent;
    > .
    > .
    > .
    > len = strlen(msg);
    > bytes_sent = send(sockfd, msg, len, 0);
    > .
    > .
    > end quote.
    >
    > len has been declared an int and Beej has strlen passing value to
    > it.But strlen returns a size_t. That's the thing I don't understand about
    > send().Bill


    Look at your system's documentation for send(). What is the type
    of its third parameter?

    Are you writing calls to functions without reading their
    documentation first? For the sake of everybody's time and sanity,
    stop doing that.

    In any case, both int and size_t are integer types. If you pass
    a value of one type to a function expecting an argument of the
    other type, it will be implicitly converted. It's likely to be
    poor style, but as long as it's within the range of both, there's
    (probably) no problem.

    --
    Keith Thompson (The_Other_Keith) <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"
     
    Keith Thompson, May 7, 2010
    #15
  16. Keith Thompson wrote:
    > "Bill Cunningham" <> writes:
    >> Keith Thompson wrote:
    >>> No, you've just been failing to understand the code you're reading.
    >>>
    >>> The author used strlen because he wanted to compute the length *of a
    >>> string*. He didn't use it "because of the size_t"; he used it
    >>> because it was the correct tool for the job.

    >>
    >> I see.
    >>
    >>> Choose which function or operator to use on the basis of what it
    >>> does and whether that meets your requirement, not just on the basis
    >>> of what type it returns.
    >>>
    >>> Don't guess.

    >>
    >> This turns upside down some of my beliefs about functions and
    >> return types. BTW I am still using quote-fix and I'm hoping the
    >> quoting is better.

    >
    > I'm having trouble figuring out what those beliefs might have been.
    > Did you think that you could look *only* at what type a function
    > returns and decide that it's the right thing? If you were writing
    > mathematical software, how would you decide whether to use sin() or
    > sqrt()?


    That would be easy. They both return doubles. So if you came across a
    function like this,

    double math(double operator);

    Then sqrt() or sin() would work. Now if you came across this,

    double math(int operator);

    I don't think you can do this,

    math(sqrt(5));

    because math takes a double as parameter. It wants something that is going
    to return a double not just an int. The int isn't big enough.

    Bill


    > Please note that I wrote "not *JUST* on the basis of what type it
    > reuturns".
     
    Bill Cunningham, May 7, 2010
    #16
  17. "Bill Cunningham" <> writes:
    > Keith Thompson wrote:

    [...]
    >> I'm having trouble figuring out what those beliefs might have been.
    >> Did you think that you could look *only* at what type a function
    >> returns and decide that it's the right thing? If you were writing
    >> mathematical software, how would you decide whether to use sin() or
    >> sqrt()?

    >
    > That would be easy. They both return doubles. So if you came across a
    > function like this,
    >
    > double math(double operator);
    >
    > Then sqrt() or sin() would work.


    Either you're trolling, or you've completely missed my point.

    Suppose you're writing code that needs to perform some mathematical
    operation.

    Question: How do you decide, at a certain point in the code,
    whether to call sqrt() or sin()?

    Answer: Call sqrt() if you need to compute a square root; call sin() if
    you need to compute a trigonometric sine.

    [snip]

    --
    Keith Thompson (The_Other_Keith) <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"
     
    Keith Thompson, May 7, 2010
    #17
  18. Keith Thompson wrote:

    [...]

    > Question: How do you decide, at a certain point in the code,
    > whether to call sqrt() or sin()?
    >
    > Answer: Call sqrt() if you need to compute a square root; call sin()
    > if you need to compute a trigonometric sine.
    >
    > [snip]


    Oh I thought we were talking about return values.

    Bill
     
    Bill Cunningham, May 8, 2010
    #18
  19. Bill Cunningham

    Tom St Denis Guest

    On May 7, 9:01 pm, Geoff <> wrote:
    > Strlen does it's work at run-time.
    > Sizeof does it's work at compile time.


    Not true. Consider:

    #include <stdio.h>

    int blah(int a) { int buf[a]; return sizeof buf; }
    int main(void) { printf("%d\n", blah(10)); return 0; }

    It's valid C99 code and should print out 40 on [most] 32-bit hosts.

    Tom
     
    Tom St Denis, May 8, 2010
    #19
  20. Bill Cunningham

    Ian Collins Guest

    On 05/ 8/10 01:10 PM, Tom St Denis wrote:
    > On May 7, 9:01 pm, Geoff<> wrote:
    >> Strlen does it's work at run-time.
    >> Sizeof does it's work at compile time.

    >
    > Not true. Consider:
    >
    > #include<stdio.h>
    >
    > int blah(int a) { int buf[a]; return sizeof buf; }
    > int main(void) { printf("%d\n", blah(10)); return 0; }
    >
    > It's valid C99 code and should print out 40 on [most] 32-bit hosts.


    Also consider

    #include <string.h>

    void f( size_t );

    int main()
    {
    const char* p = "hello world";

    f( strlen( p ) );

    return 0;
    }

    A decent compiler will optimise "strlen( p )" to 11.

    --
    Ian Collins
     
    Ian Collins, May 8, 2010
    #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. Derek
    Replies:
    7
    Views:
    24,416
    Ron Natalie
    Oct 14, 2004
  2. Thomas stegen

    Sizeof vs. Strlen

    Thomas stegen, May 27, 2004, in forum: C Programming
    Replies:
    21
    Views:
    10,461
    Barry Schwarz
    Jun 1, 2004
  3. Replies:
    82
    Views:
    3,664
    Michael Wojcik
    Aug 31, 2005
  4. Alex Vinokur
    Replies:
    7
    Views:
    513
    Clark S. Cox III
    Aug 14, 2006
  5. Alex Vinokur

    sizeof (size_t) and sizeof (pointer)

    Alex Vinokur, Nov 12, 2007, in forum: C++
    Replies:
    19
    Views:
    813
    Ben Rudiak-Gould
    Nov 30, 2007
Loading...

Share This Page