1 / 16

EEE305 Microcontroller Systems

Lecture 3: recap and more on variables, pointers and strings (omit the pink background slides) Teaching resources on on www.eej.ulst.ac.uk My office 5B18, telephone 028 90 366364 My email IJ.McCrum@ulster.ac.uk. EEE305 Microcontroller Systems.

kassia
Download Presentation

EEE305 Microcontroller Systems

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Lecture 3: recap and more on variables, pointers and strings (omit the pink background slides) Teaching resources on onwww.eej.ulst.ac.uk My office 5B18, telephone 028 90 366364 My email IJ.McCrum@ulster.ac.uk EEE305 Microcontroller Systems http://www.eej.ulst.ac.uk/~ian/modules/EEE305

  2. RECAP (red text is proper C, purple needs replaced with proper C) White space – use tabs, spaces and newlines to indent code, C is case sensitive. Commenting – put in 5 places, title and description, declarations, in front of functions and any lines worthy of extra explanation. two types, // and /* … */ Variables – Declare before use, standard types int, char, floatand double (also unsigned, signed, short and long). Examples of constants are 65, 65.0, 0x41, ‘a’, “ok” Functions – declare before use, give the types of passed parameters, the return value and the name. Library functions are predeclared for you in a .h file. You use #include <stdio.h> to access these. A function body (its definition) does not use a semicolon. Conditional tests – if(test is true){do these statements;}else{do these statements;} Tests include the equality test ==, the not equal to test != and less and greater tests <, <=, >, >=. Avoid a semicolon after the trailing ) in the test. Non-zero values are true. Conditional expression – c = (do a test) ?Assign this if true :assign this if false; Loops – do{these statements;}while(test is true); note always runs once, and note semicolon! while(test is true){do these statements;} note NO semicolon, statements gets skipped if false for(initialisation;test;increment){do these statements} note no semicolon, initial statements before entering the statement block, test done at top of block, increment done at bottom. You can exit a loop prematurely using break; , you can go back to the beginning of a loop prematurely with a continue; statement Multiple choice – the switch statement is a multi branch if . switch(test an int){ case value1:do this; break; case value2:dothis;break; default:do this;} Preprocessorstatements are a bit like search and replace in a text editor. #include <filename> and #include filename insert the file at that point in your program, the <> form uses the compilers include folder. The filenames can have any extension, .h and .c are common. #defineNAME “some text” or #defineTHING number does a simple replacement of the first thing with the second. (there are more advanced forms of this). You can do conditional compilation using #ifdefTHING …compile this #endif and there are more complicated versions of these, we shouldn’t need them. http://www.eej.ulst.ac.uk/~ian/modules/EEE305

  3. Further thoughts on variables and assignment When a compiler sees a variable declaration it puts an entry in a symbol table to records how many bytes will be needed to store its value, its name and where it can be accessed. It also stores data about the item – its storage class. There are 4 classes of variable; auto, static and extern and register. Auto storage is local, within a function. We normally do not add the auto keyword it is the default. A variable declared inside a function is only accessible within that function. A variable declared outside a function is accessible within the file it is declared in and inside any functions in that file, unless you have a local variable with the same name. We can describe the variable declared outside the function as a “global” variable, there is no global keyword in C but you can recognise it from its context. Global variables are useful but risky; you can avoid passing values or variables to a function if you let the function manipulate global variables instead. Harder to debug, ok with small programs… used in embedded C a fair bit (limited stack memory) Embedded compilers also allow a volatile keyword; a variable qualifier the data in a volatile variable can change on the fly (e.g a hardware timer, an input port or the result of an ADC or an ISR) http://www.eej.ulst.ac.uk/~ian/modules/EEE305

  4. Further thoughts on variables and assignment We will avoid writing multi file C programs but you might note there is a keyword extern used to give a variable visibility across multiple files and the keyword static is (mis)used with global variables to disallow extern use in other files (ignore this paragraph if you like!) Register is a hint to the compiler to use faster memory to keep the variable value – it is not needed now as most compilers figure out how to optimise and make code run faster. Static auto variables are placed in an area of memory where their values will be kept. The authors of C used the static keyword twice, with different meanings depending on context. What you need to know; Variables declared inside functions are only accessible within that function; they are local Variables declared outside functions are accessible anyway in the file, from that point forward – they are global to the file http://www.eej.ulst.ac.uk/~ian/modules/EEE305

  5. lvalue and rvalue of a variable In an assignment x=3; X is an lvalue expression and 3 is an rvalue expression. These do not stand for left value and right value although most of the time that is the case. I like to thing of lvalue as standing for “LOCATION value” – the address of X is what the compiler used in the expression above since it placed 3 in the contents of the storage with the address of x. There are 4 types of Lvalue that cannot be on the left side of an assignment. An array type, An incomplete type, A const-qualified type,A structure or union type with one of its members qualified as a const type The term rvalue refers to a data value that is stored at some address in memory. An rvalue is an expression that cannot have a address assigned to it. Both a literal constant and a variable can serve as an rvalue. When an lvalue appears in a context that requires an rvalue, the lvalue is implicitly converted to an rvalue. The reverse, however, is not true: an rvalue cannot be converted to an lvalue. Rvalues always have complete types or the void type. What is sometimes called 'rvalue' is the 'value of an expression’ http://www.eej.ulst.ac.uk/~ian/modules/EEE305

  6. Pointers Every variable has an address and a value, the compiler knows the size of the region of memory allocated to the variable. (in fact you can use the sizeof operator and it will tell you in bytes the size of a variables storage e.gprintf(“%d”, sizeof(x)); You can access the address of a normal variable using the & operator. (the & is also used in 2 other places in C to mean bitwise AND and logical AND) You can declare a variable to hold an address; in C this is called a pointer variable and the compiler will also know the size of the object that lives at the address pointed at. (the language B did not have this facility!) Thus you can declare a variable that will hold the address of an intor you could declare a variable that can hold the address of a char or a float. (it matters) To declare a pointer you use the * operator (this is also used in C to mean two other things, multiplication obviously and also to access a memory locations contents) You need pointers because they are useful with arrays and strings, as well as just to access and manipulate memory – buffers of data in embedded systems for example http://www.eej.ulst.ac.uk/~ian/modules/EEE305

  7. Pointers As well as declaring pointers with the * symbol it can be a useful convention to name pointers sensibly – prefix with ptr or p_ int *ptr1; // note this will hold the address of an int variable - a region of 2 bytes char *ptr2; // holds the address of a char variable – a single byte region of memory float *ptr3;// points at a region of 4 bytes in length All these pointers must themselves live in memory. On a machine with 64k of memory the pointers will need to be 16 bits in size, 2 bytes. In the microchip world pointers can be 16, 24 or 32 bits in size though it depends on the compiler as well. Pointers are not very well supported on some microcontrollers because of architectural limitations in the hardware or instruction set. (read the fine print in the compiler manual!) It is possible to declare a pointer to a void type as long as you convert it to a correct type when you use it. To do this you use what is called a void pointer void *ptr4; // there some functions that return void pointers; you “cast” these to the correct type later (e.g the malloc function returns a pointer to a big area of memory, if you want to store ints in it you cast the void pointer to an int pointer) You can add and subtract from pointers, you cannot multiply or divide. Adding 1 to a pointer will change its value by 1,2,4 or whatever the size of the pointed at object is. http://www.eej.ulst.ac.uk/~ian/modules/EEE305

  8. Simple pointer usage int y , x=42; int *ptrx; // initially ptrx holds random data, better to initialise it a null address. … ptrx=NULL; // predeclared in stdio.h, NULL is probably ((void *)0 … ptrx = &x;// we must initialise a pointers contents, with an address – e.g 1234 y = *ptrx; // in an assignment, * means the “contents of what is pointed at” // also called the indirection operator or the unary * operator // so y now has the value 42. printf(“x= %d and y = %d, x lives at address %p\n”, x , y, ptrx); … Why do we need these? - to use strings and memory. Anywhere we use arrays we can convert the code to use pointers. An array name without the brackets just holds the address of the start of the array, an array name is just a pointer (technically a const pointer – it will always hold the array address) http://www.eej.ulst.ac.uk/~ian/modules/EEE305

  9. Pointers and arrays Another way of accessing contiguous areas of memory is with pointers intnam[6]={2011, 2008, 2013, 2010, 2015, -9999}; // 12 bytes of memory note terminator int *p1; //Bye the way an array name without an index returns the start address of the array. p1=nam; // initialises p1 to the address of the array, nearly same as p1=&nam[0]; … searchyear = 2010; flag = 0; // used to indicate success do{ if(searchyear==*p1){ flag=1;break;} // remember break exits the do loop p1++; // move to next address, since we are using an int pointer we add 2 to the address }while(*p != -9999); // if flag is set then we have found the target year. http://www.eej.ulst.ac.uk/~ian/modules/EEE305

  10. Avoiding arrays #define BUFSIZE 256 int *p; // we want to point at space for 256 ints… … p=(int *)malloc(2 * 256);// better would be ( sizeof(int) * BUFSIZE ) – more portable … for(i=0;i<BUFSIZE;i++){ *(p++)=get_temperature_reading(); // assuming someone has a written the function } The reason why pointers are better than arrays is that the malloc function can take a variable – this allows the array to be resized at run time – you can run the program on several different systems and they can allocate bigger arrays if they have more memory; this is know as dynamic memory allocation. To use it requires you to test the return value of malloc, (if it fails, it returns a bad/non existent address (NULL)) We won’t need malloc on our small embedded system. Note *(p++) means get the thing that p points at, and after that increment the address (the pointer contents). There is a difference between *(p++) and (*p)++ If we use the unbracketed version *p++ we need to know the order of precedence. Turns out that the unary * and the unary increment operator have equal precedence and the rule is to associate the operators from right to left so the ++ gets done first. Always Use brackets To avoid confusion! http://www.eej.ulst.ac.uk/~ian/modules/EEE305

  11. Arrays and pointers We can interchange array and pointer declarations; sometimes we need to be sure things are initialised. So the functions below operate on arrays of chars, we use pointers. #include <stdio.h> intourstrlen (char*); // returns the number up to but not including the ‘\0’ char* ourstrcpy(char* char*); // copies the second parameter into the first including ‘\0’, // returns a pointer to the first string. There is // no warning if you copy a big string into a little string! char* ourstrcat (char* char*); // similar to strcpy except the 2nd string overwrites the 1st // strings terminating zero and you get a bigger string. intourstrcmp(char* char*); // return non zero if strings NOT the same, -ve if string 1 less If you #include <string.h> in your code you can get access to these functions, it is useful to write your own versions! http://www.eej.ulst.ac.uk/~ian/modules/EEE305

  12. Strings functions using pointers // strlen function // using arrays intourstrlen(char [] s){ inti=0; while(s[i] != ‘\0’){ i++; // bump counter return (i); } // strlen function intourstrlen(char * s){ inti=0; while(*s !=‘\0’){ i++; // bump counter s++; // bump pointer } return i; } // strcmp function – return non-zero if diff. intourstrcmp(char* d, char* s){ while(TRUE){ if(*s!=*d) return (*d-*s); if(*d == ‘\0’ || *s == ‘\0’ ) return 0; d++; s++; } } // strcpy function char *intourstrcpy(char* d, char* s){ char *temp=d; while(*sp != '\0') {*d = *s; d++; s++ } *d = '\0'; return temp; } http://www.eej.ulst.ac.uk/~ian/modules/EEE305

  13. Variables type qualifiers; const (also volatile) inti; // constint ci = 1; // ci is a constant I, you need to initialise it to be useful int *pi; // constint *pci // a pointer to a const int. You can alter pci to point to a // different const int. int *constcpi = &I; // A constant pointer, the address must be initialised and // can’t be changed. constint *constcpci = *ci; // phew…a constant pointer to a constant int. A non standard feature in some embedded compilers is the near and far keywords. These can be used with pointers as well as variables and you get similar syntax as that above. http://www.eej.ulst.ac.uk/~ian/modules/EEE305

  14. Tutorials/programming exercises Q1: experiment with the following functions; gets, strcpy and strcmp. E,g read in a line of text and see if it is your surname. #include <stdio.h> #include <string.h> #define TRUE 1 void main(void){ Char line[80],name[80],ch; puts("input your name"); strcpy(name,"IanMcCrum"); // one way to initialise a string do{ gets(line); // gets up to the terminating linefeed and adds a '\0' ch=strcmp(line,name);// return non-zero if different if(ch==0)break; // exit the do loop printf("\nNope, you entered %d chars as %s try again\n", strlen(line),line); }while(TRUE); return 0; } http://www.eej.ulst.ac.uk/~ian/modules/EEE305

  15. Tutorials/programming exercises Q2: Write a function called getline that uses the getch () function. It should read the keyboard until a newline is hit. It should store the entered keystrokes, replacing the newline with a ‘\0’ (i.e your version of gets() ); Q3: Use the gets function found in the stdio.h to read in a string of text. Print out the number of words. Call this function wordcount Q4: A line of text is input, your program should find out if it contains the text EXIT in any combination of upper or lower case letters, at any starting position in the inputted string (i.e a typical input might be “£$%^£$%^SDSDFSDFeXiT34343dfgfgf” Q5: A line of test is actually 10 numbers separated by commas. Write a program that fills an array of integers from the inputted line. Hint, get a substring then use the atoi() function. Q6: Use Sprintf to fill a string with 10 numbers separated by commas Q7: Print the biggest, smallest values of the array and its average (as a float). http://www.eej.ulst.ac.uk/~ian/modules/EEE305

  16. Summary You should be able to write C programs in a console on a PC that can process numbers, characters and strings You should be familiar with printf, sprintf puts, gets, atoi, getchar, various string functions. You should be able to work with arrays You have not covered, files – data stored on disks (fopen, fgets, fputs, fprintf, fclose or open, write, read close You have not covered structs (a collection of objects of different types) You have not covered more complex pointers, arrays of pointers, pointers to arrays, multi-dimensional arrays. How to pick up command line arguments, better console programs, graphics outputs or windows programming. The ebooks on the website are sufficient for you to learn these if you so wish http://www.eej.ulst.ac.uk/~ian/modules/EEE305

More Related