Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Programming Microcontrollers in C, 2-nd edit (Ted Van Sickle, 2001).pdf
Скачиваний:
296
Добавлен:
12.08.2013
Размер:
7.2 Mб
Скачать

114 Chapter 2 Advanced C Topics

will cause the data to be printed to the left edge of the field. Other­ wise, the data will print to the extreme right edge of the field.

Formatted input is also provided in C. The three formatted input functions are

int scanf(char* format,arg1,arg2,...); int sscanf(char* string,char* format,arg1,arg2,...);

int fscanf(FILE* fp,char* format,arg1,arg2,...);

The first of these functions reads formatted data from the standard input, the second reads formatted data from a string in memory, and the third reads formatted data from an open file fp. There is a sig­ nificant difference between the formatted inputs and outputs. Recall that the arguments in the formatted outputs are data values. In the formatted inputs, all arguments must be pointers to locations in memory that can hold the data types specified in the data string. If the program should contain

int i;

.

.

.

scanf(“%d”,i); /* BAD */

the program will probably compile, the compilers will not note an error, and the program will crash because the scanf() argument is not a pointer. It is generally recommended that you avoid use of the scanf() function.

Memory Management

There are two functions in C that allow dynamic memory man­ agement. The function

void* malloc(size_t n);

returns a pointer to a block of memory that is n bytes long. This memory is uninitialized. malloc() (and calloc() below) re­ turns a pointer to a block of memory of the type void. Therefore, before it can be used, the return pointer must be cast onto the data type that the program requires. In this case, an assignment of the return value to a pointer of the correct type will work. If this step is

Memory Management 115

not taken, none of the usual pointer arithmetic will work. If the memory is not available to be allocated, the allocation program will return a NULL.

A second dynamic memory allocation function is

void* calloc(int number, size_t n);

This function returns a pointer to a type void. It takes two arguments. The first argument is the number of items and the second argument is the size of the specific item. Therefore, if you wished to allocate space for ten TNODEs from the above problem, you should use

(TNODE *) calloc(10, sizeof(TNODE));

calloc() differs from malloc() in that it returns a pointer to initialized space. The calloc() function initializes all memory assigned by the function to zero. When memory is allocated by ei­ ther malloc() or calloc(), this memory must be returned to the system. If allocated memory is not returned to the system, even­ tually all of the available memory will be allocated. Further attempts to allocate memory will fail. If the return pointer from the allocation function is not tested and properly handled when a NULL is returned, the program will exhibit undefined behavior. This problem can be avoided by deallocating memory when it is no longer needed by the program. The function

void free(void* );

will release allocated memory. The argument in this case must be a pointer that was returned from an allocate function, either malloc() or calloc().

An additional memory allocation function is

void *realloc(void *,size_t);

The first parameter here is a pointer to a previously allocated memory block, and the second is the new size that you want for the allocated memory. This function will change the size of the allocated memory block. If you are reducing the size of the block, the pointer returned will probably be the same as that passed to realloc. If you are increasing the size of the block, and there is not enough contiguous memory available, the function will search for a proper sized block.

116 Chapter 2 Advanced C Topics

If one is found, the data stored in the original block are copied to the new block and the proper space is allocated. The pointer returned in this case will not be the same as that passed.

Miscellaneous Functions

C provides several sets of miscellaneous functions that are very useful. As mentioned earlier, the input/output functions that are prototyped in stdio.h are not parts of the language, but instead are separate functions. The miscellaneous functions are prototyped is several different header files. Many of these functions are macros, and if they are, the macro definitions are contained in the header file.

Following is a list of several header files specified by the ANSI Standard. With each header file is a list of functions or function pro­ totypes contained within these files. You should look to the documentation for your compiler to get the detailed descriptions of each of these files.

As mentioned earlier, these files are there, tested, work and are probably as robust and reliable as any code written. They do what they are supposed to, and they are free. It makes little sense to re­ write these programs just to satisfy an ego trip. I have seen shop coding standards that did not allow the use of standard library files because the programmers could not examine the source code. Such a standard is absolutely silly. If you do not trust the compiler to pro­ vide safe, satisfactory library code, you should not trust the compiler to generate any code. Therefore, you are using the wrong compiler. Get a compiler that meets your standard.

Most embedded programs that employ microcontrollers do not have standard connections to input/output devices. For example, there is rarely a terminal or a keyboard attached to an embedded system. More likely you would expect to find a numeric, or special, keypad and an LCD special purpose output display. None of the standard i/o programs can connect with such devices. In such cases, it will be your responsibility as the programmer to write drivers to interface with these devices. Also, you will rarely see disk files in your em­ bedded product. Therefore, you will rarely need to include the header file stdio.h in a microcontroller program.

 

Miscellaneous Functions 117

 

STRING OPERATIONS—Defined in string.h

strcat(s,t)

concatenate t to s

strncat(s,t,n)

concatenate n characters of t to s

strcmp(s,t)

return negative, 0, or positive

 

for s< t, s==t, or s>t respectively

strncmp(s,t,n) compare n characters of t and s

strcpy(s,t)

copy t to s

strncpy(s,t,n)

copy n characters of t to s

strchr(s,c)

point to the first c in s or ‘\0’

strrchr(s,c)

point to last c in s or ‘\0’

CHARACTER TESTS—in ctype.h

isalpha(c) non-zero if c is alphabetic, 0 if not isupper(c) non-zero if c is uppercase, 0 if not islower(c) non-zero if c is lowercase, 0 if not isdigit(c) non-zero if c is a digit, 0 if not isxdigit(c) non-zero if c is a hexadecimal digit, 0 if not isalnum(c) non-zero if c is a digit or alphabetic, zero if not isspace(c) non-zero if c is a blank, tab, newline,

return, formfeed, vertical tab, 0 if not ispunct(c) non-zero if c is a printing character except

space, letter, or digit

iscntrl(c) non-zero if c is a control character, 0 if not isgraph(c) non-zero if printing character except space isprint(c) non-zero if printing character including space toupper(c) return c converted to upper case tolower(c) return c converted to lower case

MATH FUNCTIONS—in math.h

sin(x)

sine of x, x in radians

cos(x)

cosine of x, x in radians

tan(x)

tangent of x, x in radians

asin(x)

arcsine of x, -1<=x<=1

acos(x)

arccosine of x, -1<=x<=1

atan2(x,y)

four quadrant arctan of y/x, in radians

atan(x)

two quadrant arctan of x, in radians

sinh(x)

hyperbolic sine of x

118 Chapter 2 Advanced C Topics

cosh(x)

hyperbolic cosine of x

tanh(x)

hyperbolic tangent of x

exp(x)

exponential function of x

log(x)

logarithm base e of x

log10(x)

common logarithm of x

pow(x,y)

raise x to the y power

sqrt(x)

square root of x

fabs(x)

absolute value of x

ceil(x)

smallest integer not less than x

floor(x)

largest integer not greater than x

ldexp(x,n)

x*2^n

frexp(x,int *exp) split double into mantissa and exponent modf(x,double *ip) Splits x into integral and fractional parts. Puts integral in ip and returns

fractional part. fmod(x,y) floating-point remainder of x/y

These functions all require double arguments and return double values.

Utility functions—in stdlib.h

double atof(const char *s); integer atoi(const char *s); long atol(const char *s);

double strtod(char *str,char **scanstop); long strtol(char *str,char **scanstop,int base);

unsigned long strtoul(char *str,char **scanstop,int base); ldiv_t ldiv(long numer,long denom);

div_t div(int numer,int denom); long labs(long n);

int abs(int n);

void *bsearch(void *key, void *base,size_t number,size_t size, int(*compare)(void*,void*));

void qsort(void *base,size_t number, size_t size, int(*compare)(void*,void*));

int rand(void);

int srand(unsigned int seed);

void *calloc(size_t nobj, size_t size); void *malloc(size_t size);

void *realloc(void *p, size_t size);

Miscellaneous Functions

119

 

 

void free(void *p); void abort(void);

int atexit(void(*fcn)(void)); void exit(int status);

int system(const char *name);

Non-local Jumps—in setjmp.h

int setjmp(env);

int longjmp(env,int);

Diagnostics—in assert.h

The macro assert() is defined in assert.h

Signals— in signal.h

void (*signal(int sig, void (*sighandler)(int)))(int); int raise(int sig);

Date and Time Functions —in time.h

char *asctime(struct tm *timeptr); clock_t clock(void);

char *ctime(time_t *timer);

double difftime(time_t time2, time_t time1); struct tm *gmtime(time_t *timer);

struct tm *localtime(time_t *timer); time_t mktime(struct tm *timeptr);

size_t strftime(char *buffer, size_t bufsize, char *format, struct tm *timeptr);

time_t time(time_t *timer);

Standard input and output—in stdio.h

void

clearerr(FILE *fp);

int

fclose(FILE *fp);

int

feof(FILE *fp);

int

ferror(FILE *fp);

int

fflush(FILE *fp);

int

fgetc(FILE *fp);

int

fgetpos(FILE *fp, fpos_t *pos);

char

*fgets(char *buffer, int n, FILE *fp);

FILE

*fopen(char *filename, char *access);

120 Chapter 2 Advanced C Topics

int

fprintf(FILE *fp, char *format, ...);

int

fputc(int c, FILE *fp);

int

fputs(char *string, FILE *fp);

size_t

fread(void *buffer, size_t size, size_t number, FILE

 

*fp);

FILE

*freopen(char *filename, char *mode, FILE *fp);

int

fscanf(FILE *fp, char *fs, ...);

int

fseek(FILE *fp, long offset, int origin);

int

fsetpos(FILE *fp, fpos_t *pos);

long

ftell(FILE *fp);

size_t

fwrite(void *buffer, size_t size, size_t number, FILE

 

*fp);

int

getc(FILE *fp);

char

*gets(char *buffer);

void

perror(char *string);

int

printf(char *format, ...);

int

putc(int c, FILE *fp);

int

puts(char *string);

int

remove(char *filename);

int

rename(char *oldname, char *newname);

void

rewind(FILE *fp);

int

scanf(char *format, ...);

void

setbuf(FILE *fp, char *bufptr);

int

setvbuf(FILE *fp, char *bufptr, int buftype, size_t

 

bufsize);

int

sprintf(char *s, char *format, ...);

int

sscanf(char *s, char *format, ...);

FILE

*tmpfile(void);

char

*tmpnam(char *buffer);

int

ungetc(int c, FILE *fp);

int

vfprintf(FILE *fp, char *format, va_list arglist);

int

vprintf(char *format, va_list arglist);

int

vsprintf(char *s, char *format, va_list arglist);

As you scan through the above listings, you will see many types that are not from the usual list of available types. Whenever you find such a type, the type will be either a typedef of a structure or a typedef of a standard type. These typedefs will be found in the header file where they are used.