⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 begpoint.txt

📁 有关指针的使用问题
💻 TXT
📖 第 1 页 / 共 3 页
字号:


    Another way to speed up the pointer version would be to

change:


    while (*source != '\0')     to simply    while (*source)


since the value within the parenthesis will go to zero (FALSE) at

the same time in either case.  


    At this point you might want to experiment a bit with writing

some of your own programs using pointers.  Manipulating strings

is a good place to experiment.  You might want to write your own

versions of such standard functions as:


            strlen();

            strcat();

            strchr();


and any others you might have on your system.


    We will come back to strings and their manipulation through

pointers in a future chapter.  For now, let's move on and discuss

structures for a bit.


==================================================================

CHAPTER 5: Pointers and Structures


    As you may know, we can declare the form of a block of data

containing different data types by means of a structure

declaration.  For example, a personnel file might contain

structures which look something like:


  struct tag{

       char lname[20];        /* last name */

       char fname[20];        /* first name */

       int age;               /* age */

       float rate;            /* e.g. 12.75 per hour */

       };


    Let's say we have an bunch of these structures in a disk file

and we want to read each one out and print out the first and last

name of each one so that we can have a list of the people in our

files.  The remaining information will not be printed out.  We

will want to do this printing with a function call and pass to

that function a pointer to the structure at hand.  For

demonstration purposes I will use only one structure for now. But

realize the goal is the writing of the function, not the reading

of the file which, presumably, we know how to do.


    For review, recall that we can access structure members with

the dot operator as in:


--------------- program 5.1 ------------------

#include <stdio.h>

#include <string.h>


struct tag{

       char lname[20];      /* last name */

       char fname[20];      /* first name */

       int age;             /* age */

       float rate;          /* e.g. 12.75 per hour */

       };


struct tag my_struct;       /* declare the structure m_struct */


int main(void)

{

  strcpy(my_struct.lname,"Jensen");

  strcpy(my_struct.fname,"Ted");

  printf("\n%s ",my_struct.fname);

  printf("%s\n",my_struct.lname);

  return 0;

}

-------------- end of program 5.1 --------------


    Now, this particular structure is rather small compared to

many used in C programs.  To the above we might want to add:


  date_of_hire;

  date_of_last_raise;

  last_percent_increase;

  emergency_phone;

  medical_plan;

  Social_S_Nbr;

  etc.....


    Now, if we have a large number of employees, what we want to

do manipulate the data in these structures by means of functions.

For example we might want a function print out the name of any

structure passed to it.  However, in the original C (Kernighan &

Ritchie) it was not possible to pass a structure, only a pointer

to a structure could be passed.  In ANSI C, it is now permissible

to pass the complete structure.  But, since our goal here is to

learn more about pointers, we won't pursue that.


    Anyway, if we pass the whole structure it means there must be

enough room on the stack to hold it.  With large structures this

could prove to be a problem.  However, passing a pointer uses a

minimum amount of stack space.


    In any case, since this is a discussion of pointers, we will

discuss how we go about passing a pointer to a structure and then

using it within the function.


    Consider the case described, i.e. we want a function that

will accept as a parameter a pointer to a structure and from

within that function we want to access members of the structure.

For example we want to print out the name of the employee in our

example structure.


    Okay, so we know that our pointer is going to point to a

structure declared using struct tag.  We define such a pointer

with the definition:


    struct tag *st_ptr;


and we point it to our example structure with:


    st_ptr = &my_struct;


    Now, we can access a given member by de-referencing the

pointer. But, how do we de-reference the pointer to a structure?

Well, consider the fact that we might want to use the pointer to

set the age of the employee.  We would write:


    (*st_ptr).age = 63;


    Look at this carefully.  It says, replace that within the

parenthesis with that which st_ptr points to, which is the

structure my_struct.  Thus, this breaks down to the same as

my_struct.age.


    However, this is a fairly often used expression and the

designers of C have created an alternate syntax with the same

meaning which is:


    st_ptr->age = 63;


    With that in mind, look at the following program:


------------ program 5.2 --------------


#include <stdio.h>

#include <string.h>


struct tag{                   /* the structure type */

       char lname[20];        /* last name */

       char fname[20];        /* first name */

       int age;               /* age */

       float rate;            /* e.g. 12.75 per hour */

       };


struct tag my_struct;         /* define the structure */


void show_name(struct tag *p);    /* function prototype */


int main(void)

{

  struct tag *st_ptr;         /* a pointer to a structure */

  st_ptr = &my_struct;        /* point the pointer to my_struct */

  strcpy(my_struct.lname,"Jensen");

  strcpy(my_struct.fname,"Ted");

  printf("\n%s ",my_struct.fname);

  printf("%s\n",my_struct.lname);

  my_struct.age = 63;

  show_name(st_ptr);          /* pass the pointer */

  return 0;

}



void show_name(struct tag *p)

{

  printf("\n%s ", p->fname);     /* p points to a structure */

  printf("%s ", p->lname);

  printf("%d\n", p->age);

}

-------------------- end of program 5.2 ----------------


    Again, this is a lot of information to absorb at one time.

The reader should compile and run the various code snippets and

using a debugger monitor things like my_struct and p while single

stepping through the main and following the code down into the

function to see what is happening.


==================================================================

CHAPTER 6:  Some more on Strings, and Arrays of Strings


   Well, let's go back to strings for a bit.  In the following

all assignments are to be understood as being global, i.e. made

outside of any function, including main.


   We pointed out in an earlier chapter that we could write:


   char my_string[40] = "Ted";


which would allocate space for a 40 byte array and put the string

in the first 4 bytes (three for the characters in the quotes and

a 4th to handle the terminating '\0'.


    Actually, if all we wanted to do was store the name "Ted" we

could write:


      char my_name[] = "Ted";


and the compiler would count the characters, leave room for the

nul character and store the total of the four characters in memory

the location of which would be returned by the array name, in this

case my_string.


    In some code, instead of the above, you might see:


     char *my_name = "Ted";


which is an alternate approach.  Is there a difference between

these?  The answer is.. yes.  Using the array notation 4 bytes of

storage in the static memory block are taken up, one for each

character and one for the nul character.  But, in the pointer

notation the same 4 bytes required, _plus_ N bytes to store the

pointer variable my_name (where N depends on the system but is

usually a minimum of 2 bytes and can be 4 or more).


    In the array notation, my_name is a constant (not a

variable).  In the pointer notation my_name is a variable.  As to

which is the _better_ method, that depends on what you are going

to do within the rest of the program.


    Let's now go one step further and consider what happens if

each of these definitions are done within a function as opposed

to globally outside the bounds of any function.


void my_function_A(char *ptr)

{

  char a[] = "ABCDE";

  .

  .

}


void my_function_B(char *ptr)

{

  char *cp = "ABCDE";

  .

  .

}


    Here we are dealing with automatic variables in both cases.

In my_function_A the automatic variable is the character array

a[]. In my_function_B it is the pointer cp.  While C is designed

in such a way that a stack is not required on those processors

which don't use them, my particular processor (80286) has a

stack.  I wrote a simple program incorporating functions similar

to those above and found that in my_function_A the 5 characters

in the string were all stored on the stack.  On the other hand,

in my_function_B, the 5 characters were stored in the data space

and the pointer was stored on the stack.


    By making a[] static I could force the compiler to place the

5 characters in the data space as opposed to the stack.  I did

this exercise to point out just one more difference between

dealing with arrays and dealing with pointers.  By the way, array

initialization of automatic variables as I have done in

my_function_A was illegal in the older K&R C and only "came of

age" in the newer ANSI C.  A fact that may be important when one

is considering portabilty and backwards compatability.


    As long as we are discussing the relationship/differences

between pointers and arrays, let's move on to multi-dimensional

arrays.  Consider, for example the array:


    char multi[5][10];


    Just what does this mean?   Well, let's consider it in the

following light.


        char multi[5][10];

        ^^^^^^^^^^^^^


    If we take the first, underlined, part above and consider it

to be a variable in its own right, we have an array of 10

characters with the "name"  multi[5].  But this name, in itself,

implies an array of 5 somethings.  In fact, it means an array of

five 10 character arrays.  Hence we have an array of arrays.  In

memory we might think of this as looking like:


      multi[0] = "0123456789"

      multi[1] = "abcdefghij"

      multi[2] = "ABCDEFGHIJ"

      multi[3] = "9876543210"

      multi[4] = "JIHGFEDCBA"


with individual elements being, for example:


      multi[0][3] = '3'

      multi[1][7] = 'h'

      multi[4][0] = 'J'


    Since arrays are to be contiguous, our actual memory block

for the above should look like:


    "0123456789abcdefghijABCDEFGHIJ9876543210JIHGFEDCBA"


    Now, the compiler knows how many columns are present in the

array so it can interpret multi + 1 as the address of the 'a' in

the 2nd row above.  That is, it adds 10, the number of columns,

to get this location.  If we were dealing with integers and an

array with the same dimension the compiler would add

10*sizeof(int) which, on my machine, would be 20.  Thus, the

address of the "9" in the 4th row above would be &multi[3][0] or

*(multi + 3) in pointer notation.  To get to the content of the

2nd element in row 3 we add 1 to this address and dereference the

result as in


    *(*(multi + 3) + 1)


    With a little thought we can see that:


    *(*(multi + row) + col)    and

    multi[row][col]            yield the same results.


    The following program illustrates this using integer arrays

instead of character arrays.


------------------- program 6.1 ----------------------

#include <stdio.h>


#define ROWS 5

#define COLS 10


int multi[ROWS][COLS];


int main(void)

{

  int row, col;

  for (row = 0; row < ROWS; row++)

    for(col = 0; col < COLS; col++)

      multi[row][col] = row*col;

  for (row = 0; row < ROWS; row++)

    for(col = 0; col < COLS; col++)

    {

      printf("\n%d  ",multi[row][col]);

      printf("%d ",*(*(multi + row) + col));

    }

  return 0;

}

----------------- end of program 6.1 ---------------------


    Because of the double de-referencing required in the pointer

version, the name of a 2 dimensional array is said to be a

pointer to a pointer.  With a three dimensional array we would be

dealing with an array of arrays of arrays and a pointer to a

pointer to a pointer.  Note, however, that here we have initially

set aside the block of memory for the array by defining it using

array notation.  Hence, we are dealing with an constant, not a

variable.  That is we are talking about a fixed pointer not a

variable pointer.  The dereferencing function used above permits

us to access any element in the array of arrays without the need

of changing the value of that pointer (the address of multi[0][0]

as given by the symbol "multi").


EPILOG:


    I have written the preceding material to provide an

introduction to pointers for newcomers to C.  In C, the more one

understands about pointers the greater flexibility one has in the

writing of code.  The above has just scratched the surface of the

subject. In time I hope to expand on this material.  Therefore,

if you have questions, comments, criticisms, etc. concerning that

which has been presented, I would greatly appreciate your

contacting me using one of the mail addresses cited in the

Introduction.


Ted Jensen

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -