Printing strings display smileys

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
User avatar
Roman
Member
Member
Posts: 568
Joined: Thu Mar 27, 2014 3:57 am
Location: Moscow, Russia
Contact:

Printing strings display smileys

Post by Roman »

I have the following code:

Code: Select all

unsigned char *testb = (unsigned char*) 0x300000;
printf("%d\n", *testb);
*testb = "Q";
printf("%s\n", *testb);
I expect it to print "0", then "Q", but this happens:
Image

What's wrong? My OS has no multitasking, so nothing can overwrite 0x300000...
"If you don't fail at least 90 percent of the time, you're not aiming high enough."
- Alan Kay
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: Strange code behavior.

Post by Brendan »

Hi,
Roman wrote:I have the following code:

Code: Select all

unsigned char *testb = (unsigned char*) 0x300000;
printf("%d\n", *testb);
*testb = "Q";
printf("%s\n", *testb);
The ASCII character 'Q' has the value 0x51, so "printf("%s\n", *testb);" prints the string at address 0x0000051.


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
User avatar
sortie
Member
Member
Posts: 931
Joined: Wed Mar 21, 2012 3:01 pm
Libera.chat IRC: sortie

Re: Strange code behavior.

Post by sortie »

Also did you mean 'Q' rather than "Q"?

You don't appear to understand C well. You need to learn C well immediately.
User avatar
bluemoon
Member
Member
Posts: 1761
Joined: Wed Dec 01, 2010 3:41 am
Location: Hong Kong

Re: Strange code behavior.

Post by bluemoon »

Roman wrote:*testb = "Q";
Either you use a crappy compiler, or you ignored the warning:
warning: incompatible pointer to integer conversion assigning to 'unsigned char' from 'char [2]' [-Wint-conversion]

This give a hint on "what you code is not what you wanted™". The compiler tried to put whatever "Q" mean into a single char storage.

Change that to 'Q', and add a zero terminator to the string.
User avatar
AndrewAPrice
Member
Member
Posts: 2303
Joined: Mon Jun 05, 2006 11:00 pm
Location: USA (and Australia)

Re: Strange code behavior.

Post by AndrewAPrice »

Roman wrote:What's wrong? My OS has no multitasking, so nothing can overwrite 0x300000...
Looks like your OS is happy. :)

Seriously though, double quotes are string literals (pointers to null terminates strings) while single quotes are character literals. You're writing a pointer address rather than a character value into memory. Replace "Q" with 'Q'.
My OS is Perception.
alexfru
Member
Member
Posts: 1112
Joined: Tue Mar 04, 2014 5:27 am

Re: Strange code behavior.

Post by alexfru »

Roman wrote:I have the following code:

Code: Select all

unsigned char *testb = (unsigned char*) 0x300000;
printf("%d\n", *testb);
*testb = "Q";
printf("%s\n", *testb);
What's wrong? My OS has no multitasking, so nothing can overwrite 0x300000...
You don't know enough C, that's what's wrong.

This line

Code: Select all

unsigned char *testb = (unsigned char*) 0x300000;
declares testb to be a pointer to unsigned char and initializes it with memory address 0x300000. That may be an invalid address (e.g. too large, without actual memory behind it or without access rights), btw.

This line

Code: Select all

printf("%d\n", *testb);
goes to the memory at the address that testb contains, 0x300000, grabs an unsigned char from there and calls printf() to print it as a number (e.g. ASCII code of the char). But did you store a character there (in the memory at address 0x300000), in the first place? If you didn't, what do you expect to be printed (assuming the memory is accessible and an unsigned char can be read from there)?

This line

Code: Select all

*testb = "Q";
creates a string literal in your program (2 bytes (those are C bytes, which aren't necessarily 8-bit octets!): one with the ASCII (normally, ASCII, but ultimately depends on the compiler/platform) code of the character 'Q' followed by another with code 0), in its read-only data section (one of the common places; but can also appear in the code section if it's read-only or in the regular data section if read-only/writable isn't supported by the compiler or the CPU), then it takes the memory address of it (the address of 'Q') and after converting it to type unsigned char stores to where testb points, to the memory at address 0x300000. Note, it doesn't store the code of that 'Q' there, it stores the address of that 'Q', possibly truncated and thus made invalid.

Finally, this line

Code: Select all

printf("%s\n", *testb);
goes to the memory again, fetches unsigned char from where testb points (it still points to 0x300000)... You do remember that tesb points to unsigned char, don't you? Then it takes this char (converted to int or unsigned int, depending on the size of char w.r.t. the size of int in your compiler), and passes it to printf() to print this char/int as though it actually was a pointer to an array of char containing some text terminated with a character with value 0. You're lying to printf() here, you're promising it a pointer to char (%s being the promise), but are actually giving it an int (possibly unsigned), whose alignment and size may differ from those of a pointer to char (thus, potentially making printf() access its second parameter incorrectly and damaging or crashing the program) and whose value may not be equal to a valid or expected address (thus making printf() print garbage, damage or crash the program).

So, there, you need to learn about:
- pointers
- arrays
- the relationship between the above: how arrays "decay" to pointers (that is, how they transform into pointers to the first array element)
- string literals (in 2 different contexts: a. initializers of arrays of char and arguments of sizeof, b. everywhere else (in expressions, in initializers of pointers))
- printf()
and some other things.
User avatar
iansjack
Member
Member
Posts: 4711
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: Strange code behavior.

Post by iansjack »

Apart from your other errors, what makes you so sure that the printf routine can't overwrite 0x300000? Unlikely though it is, that is an assumption that may not be true.
User avatar
Roman
Member
Member
Posts: 568
Joined: Thu Mar 27, 2014 3:57 am
Location: Moscow, Russia
Contact:

Re: Printing strings display smileys

Post by Roman »

Thanks everybody, I have got it working.
"If you don't fail at least 90 percent of the time, you're not aiming high enough."
- Alan Kay
User avatar
Roman
Member
Member
Posts: 568
Joined: Thu Mar 27, 2014 3:57 am
Location: Moscow, Russia
Contact:

Re: Printing strings display smileys

Post by Roman »

My OS laughs at my C skills.
"If you don't fail at least 90 percent of the time, you're not aiming high enough."
- Alan Kay
metallevel
Posts: 18
Joined: Thu May 17, 2012 12:43 pm
Location: in front of a computer

Re: Printing strings display smileys

Post by metallevel »

Roman wrote:My OS laughs at my C skills.
Forgive me for pointing this out, but if you're writing an OS in C, you really should be good at C :P . In fact, if you don't know C, you probably shouldn't be writing an OS at all! Even if you were writing an OS 100% in assembly, just about every low-level programmer knows C, and if you don't it could be a sign that you don't know much about programming in low-level languages in general.

I don't think a single one of those four lines of code you originally posted was doing what you thought it was doing, and I for one can't remember the last time I saw so many mistakes crammed into so little code. Even if your code seems to be working now, I can only imagine that it's corrupting memory or otherwise doing something awful without you realizing it.

Sorry to break it to you, but you need to learn a lot more about C before writing a kernel in it. Even the newest C programmer knows the difference between single and double quotes.
Post Reply