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
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
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
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.