-2
#include <iostream>
#define SIZE 2

int main(int argc, char** argv)
{
    char w = 'a';
    char *array[SIZE];
    array[0] = &w;
    std::cout << *array << std::endl;
    system("PAUSE");

    return(0);
}

The output of the program is: a╠╠╠╠┴Kôè∞≈5«,┌.

Char is one byte long so the output should be: a

Or it outputs the garbage because the pointer size is 4 bytes(for int, double, float, char) for x86 and all of the garbage is those 3 bytes?

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
Tracy
  • 59
  • 1
  • 8
  • 1
    Why aren't you just using strings? – Maximilian Burszley Apr 13 '18 at 15:34
  • @TheIncorrigible1 learning experience. – Tracy Apr 13 '18 at 15:35
  • Pretty sure C++ strings are still null terminated so what you're seeing is garbage in the memory. Not sure why you're assigning the array the location of w. – Maximilian Burszley Apr 13 '18 at 15:35
  • use printf with these types you are using. – C.J. Apr 13 '18 at 15:36
  • 1
    Possible duplicate of [Why is address of char data not displayed?](https://stackoverflow.com/questions/4860788/why-is-address-of-char-data-not-displayed) – Passer By Apr 13 '18 at 15:37
  • @TheIncorrigible1 "array" is a pointer to the first element. Right? So it's the same as char** array; I'm assining w to the first element. – Tracy Apr 13 '18 at 15:38
  • 3
    @PasserBy No, that's about not expecting a C string to be printed. Tracy does expect that, but doesn't supply a valid C string (because it points at memory that wasn't initialised with one and overruns into unrelated memory that isn't allowed for access). – underscore_d Apr 13 '18 at 15:40
  • @underscore_d Fair enough. But in my defense, it seems like the answer does explain what's going on here as well – Passer By Apr 13 '18 at 15:41
  • "learning experience" is one thing. Writing code that does seemingly arbitrary, capricious things is another. I'm not sure there's any correlation. You could instead explain why you expected this code to do anything useful (i.e. why "Char is one byte long" and why you think that's relevant here, etc.) – underscore_d Apr 13 '18 at 15:43
  • @underscore_d i have arrray of char pointers. I assing a memory address of a variable to the first of those pointers. I print the first element. It prints that character + a lot of garbage. Either i print more than one byte or there is something else. – Tracy Apr 13 '18 at 15:45
  • @Tracy What type is `*array`? If it's a `char *`, how does std::cout operate when given a `char *`? – PaulMcKenzie Apr 13 '18 at 15:47
  • 1
    Why are you addressing me? Why not read the very clear answers you have been given by others? `cout` wants a `NUL`-terminated string, and you instead give it some place in the data region of memory that was never declared as such a string. There's nothing to reason about; you're just doing it wrong. – underscore_d Apr 13 '18 at 15:47
  • @PaulMcKenzie so my it's not even about knowledge of the C/C++ spec. It's about learning how OS work. Terminal expects the null terminated string. char* is a C like string which has to be terminated with \0. – Tracy Apr 13 '18 at 15:59
  • 1
    OSes have nothing to do with it. The language defines what must happen when you pass a valid argument, and you didn't do that (so the code is broken and what happens is deeply uninteresting) – underscore_d Apr 13 '18 at 16:24
  • 1
    @Tracy You wrote -- *Char is one byte long so the output should be: a* -- Why did you say this, when it is false? The output is controlled by how `std::cout` behaves when given a `char *`. That behavior has been explained multiple times, both in the comments and in the answers given to you. Yes, you have an `'a'` character, but that is *not* what is to be expected, given **how** you've decided to display the output. – PaulMcKenzie Apr 13 '18 at 16:30
  • ╠ is 0xCC in codepage 437, and [MSVC fills 0xCC to uninitialized memory to help debugging](https://stackoverflow.com/q/370195/995714). That means you've accessed uninitialized memory. You can find tons of questions about ╠ and 0xCC here on SO – phuclv Aug 18 '18 at 10:57

4 Answers4

4
char *array[SIZE];

You're declaring an array of char pointers, each element of that array is a char*, then

char[0] = &w;

You're assigning the 0th pointer the address of variable w.

std::cout<<*array<<std::endl;

is the same as

std::cout<<array[0]<<std::endl;

You're trying to print the 0th pointer, which you set to not null-terminated string, anything can happen from there as you're reading random things from memory.

Kaldrr
  • 2,780
  • 8
  • 11
  • so *array doesn't mean "dereferencing the first element"? Spec says arrays are implicitly converted to poiners to the first elements of the array. You say i'm trying to output the addres but i actually dereference the address. Or i got it wrong? i'm dereferencing the pointer wich points to the pointer so i need to do **array? – Tracy Apr 13 '18 at 16:03
  • 1
    @Tracy - Yes, as the first element is *also* a pointer you will have to dereference `array` twice to get to the character. – Bo Persson Apr 13 '18 at 16:23
4

This has nothing to do with pointer sizes or the sizes of built-in types.

The code stores the address of a character in array[0], then sends that address to std::cout. When you insert a char* into std::cout the inserter assumes that the pointer points at a nul-terminated character array. There is no nul terminator here, so it goes on writing stuff until it hits a zero. Formally, the behavior is undefined.

You'd get the same thing, more clearly, with char* array = &w; std::cout << array << '\n';. Or, even simpler, std::cout << &w << '\n';.

To write the value of the character, use std::cout << w << '\n'; or, if you need to use that array, write out the character at the beginning of the array. That's array[0][0] or, if you like direct dereferencing, **array.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165
3

Char is one byte long so the output should be: a

That length of "one byte" hasn't been stored anywhere in your compiled program.

A pointer, like char *, to one byte is no different than a pointer to many bytes. The pointer does not know.

When you send a character pointer to std::cout, that stream is designed to output successive characters until a null character is encountered. That's how it is determined how many characters should be output. The pointer doesn't know, so the data pointed to is expected to mark its end.

Drew Dormann
  • 59,987
  • 13
  • 123
  • 180
  • It's determined by the MSVC compiler the char is one byte. – Tracy Apr 13 '18 at 15:40
  • 1
    `sizeof(char)` is 1 byte. That has nothing to do with the length of a C-style `NUL`-terminated string. – underscore_d Apr 13 '18 at 15:40
  • @Tracy Bytes don't matter in your example. – Maximilian Burszley Apr 13 '18 at 15:40
  • In my example i have array of length 2. I'm trying to print first element and not the whole array. That array is an array of char pointers where each pointer can point to everyting. In my case, it points to the char with value "w". I'm trying to print that w by printing *array, which is the first element of whatever array size i have. I would understand if i printed the whole array but it's only one char. – Tracy Apr 13 '18 at 15:49
  • 1
    @Tracy -- It doesn't matter about the bytes you set in your example. When `std::cout` is given a `char *`, it will output characters until a null character is reached. Where did you set a null byte so that the output terminates on your single character? – PaulMcKenzie Apr 13 '18 at 15:49
1

Arrays used in expressions with rare exceptions are converted to pointers to their first elements.

From the C++ Standard (4.2 Array-to-pointer conversion)

1 An lvalue or rvalue of type “array of N T” or “array of unknown bound of T” can be converted to a prvalue of type “pointer to T”. The result is a pointer to the first element of the array.

So in this statement

std::cout << *array << std::endl;

the sub-expression array has the type char ** because elements of the array have the type char *.

Thus the expression *array has the type char *. And you are trying to output a string pointed to by the pointer *array that is not zero-terminated. So the program has undefined behaviour. It outputs all characters following the character 'a' until a zero character is encountered in the memory.

You need to write

std::cout << **array << std::endl;

to output just one character.

Here is a demonstrative program

#include <iostream>

int main() 
{
    const size_t SIZE = 2;
    char w = 'a';
    char *array[SIZE];
    array[0] = &w;

    std::cout << **array << std::endl;  

    return 0;
}

Its output is

a

This statement

std::cout << *array << std::endl;

would work fine if after the character 'a' in your object there will be a zero-character that is if the statement would deal with a string.

For example

#include <iostream>

int main() 
{
    const size_t SIZE = 2;
    char w[] = { 'a', '\0' };
    char *array[SIZE];
    array[0] = &w[0];

    std::cout << *array << std::endl;   

    return 0;
}

The program output is the same as shwon above.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335