-2

When I try to copy one element from char array to a char and then from same char to another char array, second char array gives weird output, usually containing whole string from first char array. This happens only when second char array is not initialized. My question is how char is able to transfer whole string to another char array.

int main()
{
    char a[10] = "ababababa";
    char b[5];
    char temp;

    temp=a[1];
    b[0]=temp;

    std::cout<<b;

}

While using g++ I get b{�Uarabababa While using clang++ I get b�U

Content between b and U changes every time program is run.

PK2n
  • 19
  • 2

2 Answers2

1
char b[5];

Here, b is an array of 5, uninitialised chars. Inspecting their values before initialising them results in undefined behaviour.

temp=a[1];
b[0]=temp;

Here, you initialise assign only to the first element of b. The rest are still uninitialised.

std::cout<<b;

Here, you use b as an array that is interpreted as a c-string by std::cout due to array decaying (effectively, std::cout sees const char*, which, by default, is assumed to be a null-terminated c-string). Since it requires inspecting the values of all the elements inside up to the null-terminator, it does so, which invokes undefined bahaviour, because some of the values are uninitialised.

A program that invokes undefined bahaviour cannot have its outcome predicted. Literally anything can happen, which includes different behaviours on different compilers or even different behaviours between executions.

Fureeish
  • 12,533
  • 4
  • 32
  • 62
  • Thank you, it explained the situation. – PK2n Aug 05 '19 at 17:05
  • That is not initialisation. – Lightness Races in Orbit Aug 05 '19 at 17:11
  • @LightnessRacesinOrbit I suppose you mean the part where I said that "*Here, you **initialise** only the first element of `b`*" - correct, it's an assignemnt, not an initialisation. – Fureeish Aug 05 '19 at 17:15
  • That's right. "Initialising them" !== "giving them values" (though it is one way of doing so) – Lightness Races in Orbit Aug 05 '19 at 17:15
  • @LightnessRacesinOrbit corrected the post, thank you for your being vigilant. – Fureeish Aug 05 '19 at 17:16
  • @LightnessRacesinOrbit I was read a 2-3 days ago about constructors and we can make a constructor using ```initializer_list``` which allows ```={}``` initialization. So it is called initialization or assignment? – PK2n Aug 05 '19 at 17:28
  • @Pk2n you are looking for distinguishment between copy-initialisation and direct / uniform initialisation. I recommend reading further about them. – Fureeish Aug 05 '19 at 17:33
  • @Fureeish in the book it was stated that "```=``` before ```{}```" is optional. So I am confused same style of assignment is in copy constructor section of book. Here I am assuming that assignment and initialization is same, assigning given value to object. – PK2n Aug 05 '19 at 17:42
  • 1
    Assigning and initialising is not the same. However, `T t = {}` and `T t{}` most of the time are treated the same, they are not exactly the same. – Fureeish Aug 05 '19 at 18:04
  • Thank you for explaining. I'll read further. – PK2n Aug 05 '19 at 18:07
  • @PK2n The key point you may be getting confused about is that in a declaration, the initialiser is sometimes preceded by a `=`. Like `int x = 42;`. However, unlike other uses of `=`, this is _not_ assignment! Yes, it's confusing. Both of Fureeish's examples in that comment are initialisation. – Lightness Races in Orbit Aug 05 '19 at 21:39
  • @LightnessRacesinOrbit So use of ```=``` during initialization is more like special case for ```=```. From limitation of my knowledge, I am assuming that initialization and assignment is basically giving value to the object but during initializing you are provided with the constructor to help you give proper value to object, which basically decrease chance of error. – PK2n Aug 06 '19 at 17:12
  • @PK2n More or less yes – Lightness Races in Orbit Aug 07 '19 at 14:26
0

The characters in b are uninitialised, they are therefore unlikely to contain a null character. You initialise the first character to 'b' and then print the array.

The char * stream operator is invoked which determines the length of the string by scanning through it until it finds a null character. As the array doesn't contain a null character it keeps reading past the end of the array until it happens to find a null character somewhere else. In your case it looks like your compiler has stored a after b in the stack so it prints all the elements of b, some other character (perhaps b is padded up to an even number of bytes in memory) then the contents of a, stopping at the null terminator at the end of a. None of this is guaranteed and will change between compilers, operating systems and even different runs of your program. Welcome to the world of undefined behaviour.

The simple fix is to initialise b to all zeros at the beginning of your program:

#include <algorithm>
#include <iostream>

int main()
{
    char a[10] = "ababababa";
    char b[5];
    std::fill(std::begin(b), std::end(b), '\0');
    char temp;

    temp=a[1];
    b[0]=temp;

    std::cout<<b;

}

Alternatively avoid the problem completely with std::string:

#include <algorithm>
#include <iostream>

int main()
{
    std::string a = "ababababa";
    std::string b( 1, a[ 0 ] );

    std::cout<<b;

}
Alan Birtles
  • 32,622
  • 4
  • 31
  • 60
  • I started using ```std::string``` in my project, after I had issues with char array. ```std::string``` is less pain to handle. – PK2n Aug 05 '19 at 18:14