-3

Someone raised this code to me, that raised me to wonder what is going on there the code is as follow from VS 2019:

#include <stdio.h>
#include <string.h>

int main()
{
    char y = '5';
    char w = "5";
    printf("size of x %x\n",&w);
    printf("size of X %X\n", w);
    printf("size of X in number: %d \n", w);
    printf("size of Y %d\n\n", w);

    w = '5';
    printf("size of y %x\n", &w);
    printf("size of Y %X\n", w);
    printf("size of X in number: %d \n", w);
    printf("size of Y %d\n\n", w);

    return 0;
}

The output is as follow:

size of x 8ff8bb
size of X 30
size of X in number: 48
size of Y 48

size of y 8ff8bb
size of Y 35
size of X in number: 53
size of Y 53

What I wonder is what is really going on there? someone pointed out that ' is a char and " is a string, but if that is the case why can one put a string into a char here, and why is that the results?

Thanks for the answers I do understand this may not be really too relevant to use, but I wonder on what is going on there, I have just recently returned to relearn C

The code is compiled and gives no warnings in VS2019

Google search mostly give me results for how to put chars into an array and the like, was unable to find any info on this behavior

  • 3
    `"size of x %x\n",&w` - Except it's not printing a size since `&w` isn't the size of anything. – StoryTeller - Unslander Monica Apr 10 '19 at 14:06
  • 1
    This can't output anything since it [doesn't compile](http://coliru.stacked-crooked.com/a/8a08280c82e6953d). – Quentin Apr 10 '19 at 14:07
  • This code does not make any sense at all in relation to the text it prints. – klutt Apr 10 '19 at 14:07
  • Ya should have edited it, posted the code as it was given – Black Blade Apr 10 '19 at 14:08
  • 2
    `char w = "5";` will generate a warning and will most likely not do what you think it does. – klutt Apr 10 '19 at 14:09
  • I am aware that is what should happen (not compile), but as it seems VS at least compile it Now I noticed I put VSCode.. my bad, meant VS not code – Black Blade Apr 10 '19 at 14:10
  • The code you posted compiles as it should. But it does generate a warning. – klutt Apr 10 '19 at 14:12
  • 1
    The output text doesn't seem to have any relation to the values being printed. For example, the last two `printf`s in each group obviously print the same number, but have different text. – Arkku Apr 10 '19 at 14:12
  • 1
    When a program is nonsense, there's not much point in trying to make sense of what it does. – Christian Gibbons Apr 10 '19 at 14:13
  • Correct correction it indeed gives warning, but not on putting a string into a char, but in the printf – Black Blade Apr 10 '19 at 14:13
  • 2
    Why would you make your output so convoluted? You print "size of X" to show the value of `w`. Why are you making it so hard? Who are you trying to confuse? – Jonathan Wood Apr 10 '19 at 14:14
  • @ChristianGibbons maybe, but it dose make me wonder, tested it on more then one computers to see and the results seem to stick, I was told on an older compiler it will not compile (VS as well) Also that the retuslt remain the same makes me wonder if its really just random or there is a meaning behind it, even if its useless, its intresting to know – Black Blade Apr 10 '19 at 14:15
  • 1
    Anyway, no offence but there is little point in explaining why this code behaves the way it does. You should find a tutorial about strings in C and read it. – klutt Apr 10 '19 at 14:15
  • `char w = "5";` defines a string literal `"5"` and assigns its address (where the character `'5'` is located) to variable `char w`, truncating the pointer value to a `char`. The output value `0x30` (hex) or `48` (decimal) probably means that the lowest byte of the string literal's address has this value. – Bodo Apr 10 '19 at 14:16
  • @JonathanWood Its code sent to me, keepet it to the orignal given code, the names I assume where done for testing reasons on the code without bothering to make changes to the printed info – Black Blade Apr 10 '19 at 14:16
  • @Bodo I'm not sure that it's even true that the value of the pointer truncates. If `char` is a signed type, then it should overflow which, I believe, results in undefined behavior. – Christian Gibbons Apr 10 '19 at 14:17
  • Possible duplicate: [“Pointer from integer/integer from pointer without a cast” issues](https://stackoverflow.com/questions/52186834/pointer-from-integer-integer-from-pointer-without-a-cast-issues). – Lundin Apr 10 '19 at 14:21
  • 1
    @ChristianGibbons Undefined behaviour doesn't mean that it doesn't truncate. It can do anything at all, including wrap around. – Arkku Apr 10 '19 at 14:22
  • @Arkku It wasn't my intention that it cannot result in wrapping, but rather that it is not reliable to expect truncation (unless you know you are running on a system where `char` is unsigned). As such, trying to make sense of it is nonsensical. – Christian Gibbons Apr 10 '19 at 14:25

2 Answers2

4

A string is an array of characters ending in a NUL character. The data here:

"5"

This is the same as:

{'5','\0'}

When you assign the value of an array to something in C you are assigning a pointer to the first element in the array. So when you write:

char w = "5"

you are creating a character and assigning the value of it to the memory location of the first element in the array of characters, a character is not large enough to store a memory location.

Doing this:

printf("size of x %x\n",&w);

Is printing out the location of w in memory

Doing this:

printf("size of X %X\n", w);

is printing the value of w, in your case was assigned to the address of the string array, and truncated because char cannot fit an address.

If you want to use a string you should do this:

const char * w = "5"

Then you can print out the string like this:

printf("string: %s\r\n", w);

you can print out the first character in the array one of these ways

printf("char: %c\r\n", *w);
printf("char: %c\r\n", w[0]);

For the second bit when you assign w like this:

char w = '5';

printing &w prints the location in memory.

printing w with %x prints the ASCII value of '5' which is 0x35

liamcomp
  • 376
  • 1
  • 8
0

The initialization

char w = "5";

does two things:

  • Define a character literal "5" which is some memory area that contains a '5' followed by a NUL ('\0').
  • Define a variable w of type char and initialize it with the address of the string literal, i.e. the memory address where the '5' is located. The address (pointer) is converted to char which will lose parts of the value because char is normally smaller than a pointer (char*).

With

printf("size of X %X\n", w);

you print the value of char w in hexadecimal form, which probably is the least significant byte of the string literal's address.

You should better use

printf("size of X %X\n", (unsigned int)w); /* %X = unsigned int */

or

printf("size of X %hhX\n", w); /* %hhX = unsigned char or signed char */

to make the format match the argument type.

Even if this does not change the result in your case, this will make sure that the code of printf doesn't access memory which might be uninitialized or might contain unrelated data.

When I ran your code, in one case the value of w was 0xA8 which got printed as FFFFFFA8. In this case %hhX would print only A8.

I'm not sure what exactly will happen when you pass a char value to function printf while the format instructs the function to interpret the data as unsigned int. This may depend on your platform's calling conventions and the compiler implementation. Maybe on your platform all arguments of shorter data types get converted to int or unsigned int.

Bodo
  • 9,287
  • 1
  • 13
  • 29
  • Doing `printf("size of X %hhX\n", w);` and `printf("size of X %X\n", (unsigned int)w);` give the same result as before Thanks for the answer – Black Blade Apr 10 '19 at 14:49