user195488
user195488

Reputation:

Question About Why String is Truncated on First Instance of \0

I have a function which reads in a character, one byte at a time, through the serial port. After these bytes are collected, they are passed to a method to process the bytes and message.

I know how to fix the problem (fix is below), but why do my bytes get truncated when I don't perform the fix?

unsigned char dpBuf[255];
...

// Pretend dpBuf has values 0x01 0x02 0x03 0x00 0x00 0x00 0x04 0x05
..
ProcessMsg(dpBuf);
..
void ProcessMsg(unsigned char *buff)
{
    // buff comes in as 0x01 0x02 0x03 0x00 and rest is truncated
    char p[255];
    ...
    for (int i = 0; i < sizeof(buff); i++) 
    {
        sprintf(p, " 0x%X ", (unsigned char)b[i]);
    }
    ..
}

Fix:

ProcessMsg((unsigned char*)&dpBuf, length); // instead of sizeof() in the loop, use length

..

void ProcessMsg (unsigned char *buff, int length)
{
    // buff comes in as the original character string and is not truncated
    .. 
    // do for loop, print out contents

}

Upvotes: 3

Views: 1778

Answers (6)

John Dibling
John Dibling

Reputation: 101446

As everyone has said, in C++ a null-terminated char array is referred to as a string. The size of the buffer the chars are stored in can be larger then the "string length" in these terms. For example:

char inBuf [] = {0x01, 0x02, 0x03, 0x00, 0x00, 0x04, 0x05};
size_t bufSize = sizeof(inBuf);
size_t rawLen = strlen(inBuf);

...in this case the size of inBuf is 7, but strlen() returns 3.

Using ASCII you can't embed NULLs in a string. However, you can use the std::string if you want to embed NULLs. std::string is generally useful anyway, so check it out. Full working example:

#include <cstdlib>

#include <string>
#include <iostream>
using namespace std;

char inBuf [] = {0x01, 0x02, 0x03, 0x00, 0x00, 0x04, 0x05};

int main()
{
    size_t bufSize = sizeof(inBuf);
    size_t rawLen = strlen(inBuf);
    string ss(inBuf, sizeof(inBuf));
    size_t ssLen = ss.length();

    cout << "Buffer Size = " << bufSize << ", Raw string length = " << rawLen << ", std::string length = " << ssLen;

    return 0;

}

The program output is:

Buffer Size = 7, Raw string length = 3, std::string length = 7

Upvotes: 2

Jason T.
Jason T.

Reputation: 382

Sizeof(buff) returns the size of a const char * because that is the type of buff. I think the method you were looking for is strlen(buff), but even then strlen will stop when it finds a null terminator. http://www.cplusplus.com/reference/clibrary/cstring/strlen/

In standard ascii 0x00 is considered a null terminator which is generally considered the end of a c style string.

I might suggest you look at using stl strings as well http://www.cplusplus.com/reference/string/string/

Upvotes: 1

Gregory Pakosz
Gregory Pakosz

Reputation: 70204

Your code is wrong: for (int i = 0; i < sizeof(buff); i++)

It's using sizeof which in fact equivalent to calling sizeof(unsigned char*). You have to pass the length explicitely.

Upvotes: 1

Sudhanshu
Sudhanshu

Reputation: 2871

buff is a pointer and hence its size is 4. sizeof(buff) = 4 sizeof(dpBuf) = 255

You wanted the second one.

Upvotes: 3

pm100
pm100

Reputation: 50110

sizeof( buff) is asking for the size of a pointer - probably 4

Upvotes: 1

sth
sth

Reputation: 229563

buff is declared as const char*, so sizeof(buff) returns the size of such a pointer, which seems to be 4 bytes on your machine. Therefore the first four bytes of the buffer are then printed in the loop.

It doesn't matter that dpBuf is declared as an array of larger size because it is passed to the function as a pointer. To circumvent this problem you should add a parameter to the function where the size of the buffer is passed explicitly.

Upvotes: 11

Related Questions