Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using memset and memcpy correctly to initialize a character array in C++

I wanted to initialize a character array with the data from a character pointer. I wrote the following code for this:

(kindly excuse what I am doing with the structure and all .. actually this code is supposed to fit into something bigger and hence the strangeness of that structure and its use)

#include <iostream>
#include <string>

struct ABC 
{
    char a;
    char b;
    char c[16];
};

int main(int argc, char const *argv[])
{
    struct ABC** abc;
    std::string _r = "Ritwik";
    const char* r = _r.c_str();

    if (_r.length() <= sizeof((*abc)->c))
    {
        int padding = sizeof((*abc)->c) - _r.length();

        std::cout<<"Size of `c` variable is : "<<sizeof((*abc)->c)<<std::endl;
        std::cout<<"Value of padding is calculated to be : "<<padding<<std::endl;

        char segment_listing[ sizeof((*abc)->c)]; 

        std::cout<<"sizeof segment_listing is "<<sizeof(segment_listing)<<std::endl;

        memcpy(segment_listing, r, _r.length());
        memset( (segment_listing + _r.length()), ' ', padding);

        std::cout<<segment_listing<<std::endl;

    }
    return 0;
}

However, when I run my code I get these wierd characters at the end of my string:

(rh4dev01:~/rough) rghosh> ./crptr
Size of `c` variable is : 16
Value of padding is calculated to be : 10
sizeof segment_listing is 16
Ritwik          °×
(rh4dev01:~/rough) rghosh> ./crptr
Size of `c` variable is : 16
Value of padding is calculated to be : 10
sizeof segment_listing is 16
Ritwik           Ñ
(rh4dev01:~/rough) rghosh> ./crptr
Size of `c` variable is : 16
Value of padding is calculated to be : 10
sizeof segment_listing is 16
Ritwik          g
(rh4dev01:~/rough) rghosh> ./crptr
Size of `c` variable is : 16
Value of padding is calculated to be : 10
sizeof segment_listing is 16
Ritwik          pô
(rh4dev01:~/rough) rghosh> ./crptr
Size of `c` variable is : 16
Value of padding is calculated to be : 10
sizeof segment_listing is 16
Ritwik
(rh4dev01:~/rough) rghosh> ./crptr
Size of `c` variable is : 16
Value of padding is calculated to be : 10
sizeof segment_listing is 16
Ritwik          àå
(rh4dev01:~/rough) rghosh> ./crptr
Size of `c` variable is : 16
Value of padding is calculated to be : 10
sizeof segment_listing is 16
Ritwik           »
(rh4dev01:~/rough) rghosh> ./crptr
Size of `c` variable is : 16
Value of padding is calculated to be : 10
sizeof segment_listing is 16
Ritwik          pZ

Can you please explain why that is happening ? Since I am printing only a character array taht is only 16 characters in length, shouldn't only 16 characters get printed ? Where are those two (sometimes zero and sometimes one) characters coming from ?

More importantly, am I corrupting any memory (that does not belong to my character array c) by my padding ?

like image 773
Chani Avatar asked May 30 '13 17:05

Chani


2 Answers

Your string needs to be NUL terminated.

    memcpy(segment_listing, r, _r.length());
    memset( (segment_listing + _r.length()), ' ', padding-1);
    segment_listing[_r.length() + padding - 1] = '\0';

Perhaps you would be better served by using snprintf(), which will add the terminator for you:

    snprintf(segment_listing, sizeof(segment_listing), "%-*s",
             (int)sizeof(segment_listing)-1, r);
like image 96
jxh Avatar answered Oct 03 '22 16:10

jxh


A C string is terminated by a 0 byte, which you havn't accounted for anywhere. You need to terminate your string with the value 0, and you'll have to take that extra byte in account in all your calculations.

like image 30
nos Avatar answered Oct 03 '22 16:10

nos