📄 chapter 8 arrays and strings -- valvano.htm
字号:
<ADDRESS>Listing 8-2: Example showing array references</ADDRESS>
<P> </P>
<P><B><I><FONT face=Helvetica,Arial><A name=NAMES></A>Pointers and Array
Names</FONT></I></B></P>
<P><FONT face="Times New Roman,Times">The examples in the section suggest that
pointers and array names might be used interchangeably. And, in many cases, they
may. C will let us subscript pointers and also use array names as addresses. In
the following example, the pointer <B>pt</B> contains the address of an array of
integers. Notice the expression <B>pt[3]</B> is equivalent to <B>*(pt+3)</B>.
</FONT></P>
<DIR>
<P><CODE>short *pt,data[5]; /* a pointer, and an array */<BR>void
Set(void){<BR> pt=data; /*
set pt to the address of data
*/<BR> data[2]=5; /* set the third
element of data to 5
*/<BR> pt[2]=5; /* set the
third element of data to 5
*/<BR> *(pt+2)=5; /* set the third
element of data to 5 */<BR>}</CODE></P></DIR>
<ADDRESS>Listing 8-3: Example showing pointers to access array
elements</ADDRESS>
<P> </P>
<P><FONT face="Times New Roman,Times">It is important to realize that although C
accepts unsubscripted array names at addresses, they are not the same as
pointers. In the following example, we can not place the unsubscripted array
name on the left-hand-side of an assignment statement.</FONT></P>
<DIR>
<P><CODE>short buffer[5],data[5]; /* two arrays */<BR>void
Set(void){<BR> data=buffer; /*
illegal assignment */<BR>}</CODE></P></DIR>
<ADDRESS>Listing 8-4: Example showing an illegal array assignment</ADDRESS>
<P> </P>
<P><FONT face="Times New Roman,Times">Since the unsubscripted array name is its
address, the statement <B>data=buffer; </B>is an attempt to change its address.
What sense would that make? The array, like any object, has a fixed home in
memory; therefore, its address cannot be changed. We say that array is not a
<B><I>lvalue</I></B>; that is, it cannot be used on the left side of an
assignment operator (nor may it be operated on by increment or decrement
operators). It simply cannot be changed. Not only does this assignment make no
sense, it is physically impossible because an array address is not a variable.
There is no place reserved in memory for an array's address to reside, only the
elements.</FONT></P>
<P> </P>
<P><B><I><FONT face=Helvetica,Arial><A name=NEGATIVE></A>Negative
Subscripts</FONT></I></B></P>
<P><FONT face="Times New Roman,Times">Since a pointer may point to any element
of an array, not just the first one, it follows that negative subscripts applied
to pointers might well yield array references that are in bounds. This sort of
thing might be useful in situations where there is a relationship between
successive elements in an array and it becomes necessary to reference an element
preceding the one being pointed to. In the following example, <B>data</B> is an
array containing time-dependent (or space-dependent) information. If pt points
to an element in the array, <B>pt[-1]</B> is the previous element and
<B>pt[1]</B> is the following one. The function calculates the second derivative
using a simple discrete derivative. </FONT></P>
<DIR>
<P><CODE>short *pt,data[100]; /* a pointer and an array */<BR>void
CalcSecond(void){ short
d2Vdt2;<BR> for(pt=data+1;pt<data+99;pt++)<BR> d2Vdt2=(pt[-1]-2*pt[0]+pt[1]);<BR>}</CODE></P></DIR>
<ADDRESS>Listing 8-5: Example showing negative array subscripting</ADDRESS>
<P> </P>
<P><B><I><FONT face=Helvetica,Arial><A name=ADDRESSARITHMETIC></A>Address
Arithmetic</FONT></I></B></P>
<P><FONT face="Times New Roman,Times">As we have seen, addresses (pointers,
array names, and values produced by the address operator) may be used freely in
expressions. This one fact is responsible for much of the power of C.</FONT></P>
<P><FONT face="Times New Roman,Times">As with pointers (<A
href="http://www.ece.utexas.edu/~valvano/embed/chap7/chap7.htm">Chapter 7</A>),
all addresses are treated as unsigned quantities. Therefore, only unsigned
operations are performed on them. Of all the arithmetic operations that could be
performed on addresses only two make sense, displacing an address by a positive
or negative amount, and taking the difference between two addresses. All others,
though permissible, yield meaningless results.</FONT></P>
<P><FONT face="Times New Roman,Times">Displacing an address can be done either
by means of subscripts or by use of the plus and minus operators, as we saw
earlier. These operations should be used only when the original address and the
displaced address refer to positions in the same array or data structure. Any
other situation would assume a knowledge of how memory is organized and would,
therefore, be ill-advised for portability reasons.</FONT></P>
<P><FONT face="Times New Roman,Times">As we saw in <A
href="http://www.ece.utexas.edu/~valvano/embed/chap7/chap7.htm">Chapter 7</A>,
taking the difference of two addresses is a special case in which the compiler
interprets the result as the number of objects lying between the addresses.
</FONT></P>
<P> </P>
<P><B><I><FONT face=Helvetica,Arial><A name=STRINGH></A>String Functions in
string.h</FONT></I></B></P>
<P><FONT face="Times New Roman,Times">ICC11 and ICC12 implement many useful
string manipulation functions. Recall that strings are 8-bit arrays with a
null-termination. The prototypes for these functions can be found in the
<B>string.h</B> file. You simply include this file whenever you wish to use any
of these routines. The rest of this section explains the functions one by one.
ICC11 and ICC12 treat each of the counts as an unsigned 16-bit
integer.</FONT></P>
<DIR>
<P><CODE>typedef unsigned int size_t;<BR>void *memchr(void *, int,
size_t);<BR>int memcmp(void *, void *, size_t);<BR>void *memcpy(void *, void *,
size_t);<BR>void *memmove(void *, void *, size_t);<BR>void *memset(void *, int,
size_t);<BR>char *strcat(char *, const char *);<BR>char *strchr(const char *,
int);<BR>int strcmp(const char *, const char *);<BR>int strcoll(const char *,
const char *);<BR>char *strcpy(char *, const char *);<BR>size_t strcspn(const
char *, const char *);<BR>size_t strlen(const char *);<BR>char *strncat(char *,
const char *, size_t);<BR>int strncmp(const char *, const char *,
size_t);<BR>char *strncpy(char *, const char *, size_t);<BR>char *strpbrk(const
char *, const char *);<BR>char *strrchr(const char *, int);<BR>size_t
strspn(const char *, const char *);<BR>char *strstr(const char *, const char
*);</CODE></P></DIR>
<ADDRESS>Listing 8-6: Prototypes for string functions</ADDRESS>
<P><FONT face="Times New Roman,Times">The first five functions are
general-purpose memory handling routines.</FONT></P>
<UL>
<P><CODE>void *memchr(void *p, int c, size_t n);</CODE></P></UL>
<P><FONT face="Times New Roman,Times">Starting in memory at address p,
<B>memchr</B> will search for the first unsigned 8-bit byte that matches the
value in <B>c</B>. At most n bytes are searched. If successful, a pointer to the
8-bit byte is returned, otherwise a NULL pointer is returned.</FONT></P>
<UL>
<P><CODE>int memcmp(void *p, void *q, size_t n);</CODE></P></UL>
<P><FONT face="Times New Roman,Times">Assuming the two pointers are directed at
8-bit data blocks of size <B>n</B>, <B>memcmp</B> will return a negative value
if the block pointed to by <B>p</B>is lexicographically less than the block
pointed to by <B>q</B>. The return value will be zero if they match, and
positive if the block pointed to by <B>p</B>is lexicographically greater than
the block pointed to by <B>q</B>.</FONT></P>
<UL>
<P><CODE>void *memcpy(void *dst, void *src, size_t n);</CODE></P></UL>
<P><FONT face="Times New Roman,Times">Assuming the two pointers are directed at
8-bit data blocks of size n, <B>memcpy</B> will copy the data pointed to by
pointer <B>src</B>, placing it in the memory block pointed to by pointer
<B>dst</B>. The pointer <B>dst</B> is returned.</FONT></P>
<UL>
<P><CODE>void *memmove(void *dst, void *src, size_t);</CODE></P>
<P><FONT face="Times New Roman,Times">Assuming the two pointers are directed
at 8-bit data blocks of size n, <B>memmove</B> will copy the data pointed to
by pointer <B>src</B>, placing it in the memory block pointed to by pointer
<B>dst</B>. This routine works even if the blocks overlap. The pointer
<B>dst</B> is returned.</FONT></P></UL>
<P><CODE>void *memset(void *p, int c, size_t n);</CODE></P>
<P><FONT face="Times New Roman,Times">Starting in memory at address p,
<B>memset</B> will set n 8-bit bytes to the 8-bit value in c. The pointer
<B>p</B>is returned.</FONT></P>
<P><FONT face="Times New Roman,Times">The remaining functions are
string-handling routines.</FONT></P>
<UL>
<P><CODE>char *strcat(char *p, const char *q);</CODE></P></UL>
<P><FONT face="Times New Roman,Times">Assuming the two pointers are directed at
two null-terminated strings, <B>strcat</B> will append a copy of the string
pointed to by pointer <B>q</B>, placing it the end of the string pointed to by
pointer <B>p</B>. The pointer <B>p</B>is returned. It is the programmer's
responsibility to ensure the destination buffer is large enough.</FONT></P>
<UL>
<P><CODE>char *strchr(const char *p, int c);</CODE></P></UL>
<P><FONT face="Times New Roman,Times">Assuming the pointer is directed at a
null-terminated string. Starting in memory at address p, <B>strchr</B> will
search for the first unsigned 8-bit byte that matches the value in c. It will
search until a match is found or stop at the end of the string. If successful, a
pointer to the 8-bit byte is returned, otherwise a NULL pointer is
returned.</FONT></P>
<UL>
<P><CODE>int strcmp(const char *p, const char *q);<BR>int strcoll(const char
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -