Presentations

Printf Case Study

Description
introduction to programming printf case study
Categories
Published
of 14
All materials on our website are shared by users. If you have any questions about copyright issues, please report us to resolve them. We are always happy to assist you.
Related Documents
Share
Transcript
  Printf Case Study   Prerequisites : Basic Pointers, Arrays, String Literals, Stack Frames Goal : Reinforce our understanding of pointers by solving a real problem that requires them (can't be solved without pointers). Overview : In this case study we'll exploit our knowledge of stack frames on Visual Studio for x86 and write some C code that reads parameter values directly from the stack. This C code will be specific to Visual Studio on x86 platforms (i.e., it is NOT portable code and is NOT a good example of how to solve this type of problems generally), but it will very nicely demonstrate how we can draw diagrams of the internal state of our program variables and then use those diagrams to write correct, non-trivial code using pointers. C/C++ language constructs and concepts demonstrated : character strings, int* pointers, char* pointers, char** pointers Background Printf is a function we use all the time and we rarely (if ever) give any thought to how it works. We know it performs output (to the screen), and that it will format and output just about anything we want it to. For example, we can output something simple like: printf( Hello World!\n ); Or, we can output something more complex like: printf( The circuit's impedance is %f + %fj\n , real_imp, imag_imp); Somehow, printf has to determine both what values we want to display and how we want those values formatted. As programmers we know to use the % sequences (such as %f in the example above) to describe what and how we want things formatted, but how does printf do its thing? In this case study we’ll write our own printf function. We’ll only implement a small fraction of the functionality provided by the Standard C library’s printf, but we’ll cover most of the important aspects of printf.  As we go through this case study we’ll discover that pointers are the key to being able to extract the values from the stack. We’ll do some pointer arithmetic to calculate the address of the values we want on the stack, we’ll declare pointers of the correct type to ensure that we read these values correctly and we’ll even spend a little bit of time (very little) discussion how we format those values for output. The putchar function  We’re not going to build then entire functionality of printf from scratch. Our starting point will be the putchar function. Putchar is a very simple function (from the Standard C library) that formats and outputs a single ASCII character. For example, if you invoke putchar(65), then you will get the letter “A” displayed on the sc reen. That’s because in the ASCII table, row 65 is assigned the character “A”. Of course, displaying a character actually requires a fairly complex bit of hardware and software to light up all the right pixels on your display, not to mention the esoteric art of designing character fonts  –  cool stuff, but way outside the bounds of what we need to learn in EE312. Printf version 1, just the basics We’re ready to jump in and get started. Printf, in its most basic usage is actually quite simple. Given an invocation like: printf( Hello World!\n ); All we need to do is output each of the ASCII characters one-at-a-time using putchar. A loop will take care of that easily. void printf_v1(char fmt[]) { uint32_t k = 0; while (fmt[k] != 0) { putchar(fmt[k k += 1; } }   Codereview In this incarnation of printf, we have just a single parameter. I’ve named the parameter “fmt”, which is shorthand for “format string”. I like that name because the first argument provided to printf is the formatting instructions for this output operation  –  it tells us what characters are to be displayed, and also contains the %f, %d and similar formatting instructions for all the other outputs. I’ve followed my own personal style of declaring fmt using the array declaration syntax (i.e., the []), even though I know full well that fmt is actually a pointer. I use the [] syntax whenever I have a parameter that points to an array. I use the * syntax to declare parameters that point at single variables. Of course, the compiler doesn’t care, and both “ char fmt[] ” and “ char* fmt ” mean the same thing. You’ll also note that I’m using a while  loop rather than a for   loop. That’s another element of my style where I try to use for  when the iteration takes place over a well defined range (e.g., from 1 to 10), and where I try to use while  when the iteration continues until something special happens. In this case, I don’t know in advance how many characters are in the format string, so I use a while loop that continues until it detects the terminating zero at the end of the format string. Finally, you may have noticed that I describe the terminating zero as 0. That, of course, is what it is  –  the number zero. Some programmers prefer to write that zero using the syntax ‘ \ 0’. Please  don’t get confused, 0 and ‘ \ 0’ are the same thing. For that matter, 0 and 0x0 are the same thing too. Just be careful not to confuse ‘ \ 0’ and ‘0’ which are quite different (‘0’ is actually the number 48). This version of printf is very limited. Printf_v1 simply prints the format string verbatim. If you try something like: printf( the number is %d\n , 42); then you’ll see “the number is %d” as your output. Note that the \ n is handled just fine. That’s because  \ n is really just the number 10 (row 10 in the ASCII table is “line feed” –   i.e., new line). That’s worth repeating, just to be sure…. \n is NOT a \ character followed by the letter n. It is a single character representing the “new line” operation. That character happens to be 10 in the ASCII table (line feed). However, the %d formatting code is completely ignored by printf_v1. That’s because we didn’t even attempt to take care of this case. Time to move on to version 2. Printf version 2  –   one decimal argument Our first big challenge comes when we try to make printf extract a value from the stack. Consider the invocation: printf_v2( the number is %d\n , 42); In this invocation we have two arguments passed to printf. The first (as always) is a format string. The second is the value 42 (on our platform this is a 32-bit signed integer). We understand how stack frames work, so we can certainly imagine how these two arguments would be arranged on the stack.    In the diagram, I’ve illustrated the stack frame for a myPrintf function with one formal parameter (i.e., one parameter that is declared in the parameter list), but has been supplied with two actual arguments. I’ve also illustrated the  stack frame so that it contains two local variables, the variable k   which is used as before to index into the format string, and a new variable p which is a pointer. This diagram corresponds with the following function: void printf_v2(char* fmt, ...) { uint32_t k; int32_t* p; } Note that the parameter list for printf_v2 has one formal argument (declared as a pointer this time, but as I’m sure you remember array parameters and pointer parameters are the same thing –   I’m using pointer syntax in this case to remind you that the actual argument will be an address). After the declaration of  fmt    I have the C/C++ ellipses expression: “, …” The ellipses means that printf_v2 is a function that can accept extra arguments. If you declare a function with ellipses, then you can call that function with as many extra arguments as you wish. The extra arguments can be any type (characters, integers, strings, floats, etc.). You can also have zero extra arguments. For this case, the extra argument is 42. Now that we’ve become familiar with the terra in, we have three problems we have to solve. (1) We need to locate the memory location where the extra argument is stored, (2) We need to determine when the argument is supposed to be printed (i.e., where the %d is inside the format string), and (3) we need to actually format the output in decimal. The first problem is by far the most interesting, finding the memory location with the 42 in it. Our diagram actually makes this pretty easy. There are actually a couple of ways I can go about finding this addres s. In the first method, I’m can make the pointer  p  point at the variable k  , and then I’ll increment  p   by 4. In the second case, I’ll make the pointer  p  point at the Stack Frame for main function   Stack Frame for myPrintf function  
We Need Your Support
Thank you for visiting our website and your interest in our free products and services. We are nonprofit website to share and download documents. To the running of this website, we need your help to support us.

Thanks to everyone for your continued support.

No, Thanks
SAVE OUR EARTH

We need your sign to support Project to invent "SMART AND CONTROLLABLE REFLECTIVE BALLOONS" to cover the Sun and Save Our Earth.

More details...

Sign Now!

We are very appreciated for your Prompt Action!

x