2015年6月1日 星期一

[C] Pointers on C - note 1

/********************************************************************/


1.
    return Exit_SUCCESS;  ==  return 0;   //  program hasn't error.
    return Exit_FAILURE;   // program is having error.
 


/********************************************************************/

2.
    char input [100];
    gets(intput);   // 同scanf一樣道理, 但scanf不食空白, gets會食埋空白!



/********************************************************************/



3.
   while( num < max && scanf( "%d", &columns[num] ) == 1
    &&columns[num] >= 0 )

    scanf( "%d", &columns[num] ) == 1
    //  scanf 第2個參數needs address, 完成後會return返總共讀取了多少個值
    //  == 1 即確保讀入的總量是1 , -1 即讀取失敗



/********************************************************************/



4.

    puts( "Last column number is not paired." ); // 同printf同樣道理,但只會輸出文字, 不能包括變量
   exit( EXIT_FAILURE );  // 即時結束程序




/********************************************************************/



5.
while( (ch = getchar()) != EOF && ch != '\n' )
   // 主要用以識別'\n' , 即enter
   // getchar() 可以每次取讀一個字符
   // EOF == -1 , 指完成輸入



/********************************************************************/


 
6.

char *output;
char const *input;    // const == 常數, 不能在程序中修改其值


strncpy( output , input, 10);


// char * strncpy ( char * destination, const char * source, size_t num );
// 把參數2的參數3個字符抄寫到參數1中




/********************************************************************/



7.
    Here is a better way to logically delete code in a C program
 
    #if 0
              statements
    #endif   



/********************************************************************/



8.

   #include <stdio.h>
   #define MAX_COLS       20

   These two lines are Preprocessor Directive(前置指令)




/********************************************************************/


9.

P. 40/609

There are only four basic data types in C – 

 1. integers, 
 2. floating‐point values, 
 3. pointers,
 4. aggregate types such as arrays and structures.

 All other types are derived from some combination of these four.


   


 *//********************************************************************/


10.

P. 43/609

Integers can be given in octal (8進制) by starting with the digit zero,
or in hexadecimal by starting with 0x, as in

0173 0177777 000060   // octal

0x7b 0xFFFF 0xabcdef00  // hexadecimal





/********************************************************************/


/********************************************************************/

11.

typedef char *ptr_to_char;
ptr_tochar a;


/********************************************************************/

12.

int *pi;
// pi is an ordinary pointer to an integer.

int const *pci;
// pci is a pointer to a constant integer. You can change the pointer’s value but not the
value to which it points.


int * const cpi;
// which is a constant pointer to an integer. Here the pointer is the constant; its value
cannot change, but you are free to modify the integer to which it points.
// cpi不可再指其他integer address,但可以修改其指緊的integer的value


int const * const cpci
// Finally, there is cpci; in this example both the pointer and the value to which it points
are constant;



/********************************************************************/


13.

P.86

There is one situation in which many claim that a goto might be
appropriate in a well structured program—breaking out of nested loops.

Because the break statement only affects the innermost loop that encloses it, the only way to
immediately exit a deeply nested set of loops is with a goto, as shown in this example.


  1. while( condition1 ){
  2. while( condition2 ){
  3. while( condition3 ){
  4. if( some disaster )
  5. goto quit;
  6. }
  7. }
  8. }
  9. quit: ;


There are two alternatives to using a goto. First, a status flag can be set when
you want to exit all of the loops, but the flag must then be tested in every loop:

  1. enum { EXIT, OK } status;
  2. ...
  3. status = OK;
  4. while( status == OK && condition1 ){
  5. while( status == OK && condition2 ){
  6. while( condition3 ){
  7. if( some disaster ){
  8. status = EXIT;
  9. break;
  10. }
  11. }
  12. }
  13. }


/********************************************************************/



14.

% is the modulo operator


/********************************************************************/



15.

P.95

shift simply slides the bits in a value to the
left or the right. On a left shift, bits on the left side of the value are discarded, and zero
bits are put into the space created on the right side by the shift,

The left shift operator is << and the right shift operator is >>.


/********************************************************************/



16.

P. 98


a = x = y + 3;

The assignment operator associates (is evaluated) from right to left, so this statement is
equivalent to:

a = ( x = y + 3 );


/********************************************************************/



17.

P.101

There are a number of unary(一元) operators, that is, operators that take only one operand.

They are

!   ++   -   &    sizeof     ~   --   +   *   (type)


/********************************************************************/



18.

The sizeof operator determines the size of its operand, measured in bytes

sizeof(int) // returns the number of bytes in an integer variable == 4bytes == 32bits



/********************************************************************/



19.

P.110

C does not have an explicit Boolean type so integers are used instead. The rule is.
Zero is false, and any nonzero value is true



/********************************************************************/




20.

P.111

Here is another shortcut that programmers often use with if statements – one in
which this same kind of trouble can occur. Assuming that you have made the
following #defineʹs, then each of the pairs of statements below seem equivalent.

#define FALSE 0
#define TRUE 1
...
if( flag == FALSE ) ...
if( !flag ) ...



/********************************************************************/




21.

P.112

An L‐value is something that can appear on the left side of an equal sign (L for
left). An R‐value is something that can appear on the right side of an equal sign. Here is
an example:

a = b + 25;

a is an L‐value because it identifies a place where a result can be stored. b + 25 is an R-value
because it designates a value.



/********************************************************************/




22.

P.114

This fragment of code contains a potential problem.


  1. int a = 5000;
  2. int b = 25;
  3. long c = a * b;


The problem is that the expression a * b is evaluated using integer arithmetic.
This code works fine on machines with 32‐bit integers, but the multiplication overflows on
machines with 16‐bit integers, so c is initialized to the wrong value.


The solution is to convert one (or both) of the values to a long before the
multiplication.


  1. long c = (long)a * b;


It is possible to lose precision when converting an integer to a float. Floating
values are only required to have six decimal digits of precision; if an integer that is
longer than six digits is assigned to a float, the result may be only an approximation of
the integer value.



/********************************************************************/



23.

P.118


  1. /*
  2. ** A program to demonstrate that the order of expression evaluation
  3. ** is only partially determined by operator precedence.
  4. */
  5. main()
  6. {
  7. int i = 10;
  8. i = i-- - --i * ( i = -3 ) * i++ + ++i;
  9. printf( "i = %d\n", i );
  10. }



// output : 4
// 由於以上程序是illegal, 所以不同compiler會出現不同的output







 














/********************************************************************/



24.

P. 120

+ (addition)
- (subtraction)
* (multiplication)
 / (division)
 % (modulo)

<< and >> operators perform left and right shifts,



/********************************************************************/




25

P.130

On many modern machines, each byte contains eight bits,
which can store unsigned integers from 0 to 255 or signed integers from ‐128 to 127.




/********************************************************************/



26.


*(int *)100 = 25;
The cast converts the value 100 from an ʺintegerʺ to a ʺpointer to an integer.ʺ




/********************************************************************/



27.

P.141

Pointer to pointer

int a = 12;
int *b = &a;
int **c = &b;

It is legal, pointer c now is pointing to the location of integer variable a.
int **c = &b;  // this expression is equivalent to *(*c).


/********************************************************************/



28.

P. 145

*cp + 1
// * has a higher precedence than +
// A copy of this value is taken and added to one, giving the character 'b' as a
result
// The final result does not reside in any identifiable location, so this expression is not a legal
L‐value.



/********************************************************************/


29.

P. 146

*cp++  // First * , then ++
*++cp  // First ++, then *
++*cp  // First * , then ++


Example :


Given :

  1. int main(){

  2. int a = 10;
  3. *(&a + 1) = 999;
  4. int *p = &a;

  5. // each cases
  6.         // ................

  7. system("pause");
  8. return 0;

  9. }


/* case 1 */
printf("%d", *p++);
> output : 10

/* case 2 */
printf("%d", *++p);
> output : 999

/* case 3 */
printf("%d", ++*p);
> output : 11

/* case 4 */
printf("%d", (*p)++);
> output : 10

/* case 5 */
printf("%d", ++*++p);
> output : 1000

/* case 6 */
printf("%d", ++*p++);
> output : 11



/********************************************************************/




30.

P. 149

Here are some sample programs to illustrate a few common pointer expressions.
Program 6.1 computes the length of a string. You should never have to write this
function because the library contains one, but it is a useful example.

  1. /*
  2. ** Compute the length of a string.
  3. */
  4. #include <stdlib.h>
  5. size_t
  6. strlen( char *string )
  7. {
  8. int length = 0;
  9. /*
  10. ** Advance through the string, counting characters
  11. ** until the terminating NUL byte is reached.
  12. */
  13. while( *string++ != '\0' )
  14. length += 1;
  15. return length;
  16. }




/********************************************************************/


31.

P. 156


int pointer - int pointer 的情況,

For example, if p1 points to array[i] and p2 points to
array[j] then p2 – p1 will have the same value as j – i.

例如 array[i] location = 1000,  array[j] location = 1024,
p2 - p1 =  6

* int = 32bit = 4bytes



/********************************************************************/

32.

P.157

Relational operations on pointers are also constrained. It is possible to compare two
pointer values with the relational operators
< <= > >=



  1. #define N_VALUES 5
  2. float values[N_VALUES];
  3. float *vp;
  4. for( vp = &values[0]; vp < &values[N_VALUES]; )
  5. *vp++ = 0;

/********************************************************************/

33.

P.167


  1. /*
  2. ** Find the place in an array where a particular integer value
  3. ** is stored, and return a pointer to that location.
  4. */
  5. #include <stdio.h>
  6. int *
  7. find_int( int key, int array[], int array_len )
  8. {
  9. int i;
  10. /*
  11. ** For each location in the array ...
  12. */
  13. for( i = 0; i < array_len; i += 1 )
  14. /*
  15. ** Check the location for the desired value.
  16. */
  17. if( array[ i ] == key )
  18. return &array[ i ];
  19. return NULL;
  20. }

/********************************************************************/


34.

P. 198

The type of b[4] is integer,
The type of b is "constant pointer to int ".


"c = &a[0];"  ===  "c=a;"


/********************************************************************/


35.

p.199

int a[10];
int b[10];

b = a <-- illegal , b and a are constant pointer, so it cannot be changed.


/********************************************************************/


36.

P.201

A subscript = b[10]

- is a indirection expression


/********************************************************************/


37.

P.202

int array[5] = {1,2,3,4,5};

2[array]   is  legal  // ans = 3

- It same as *(array+2)


/********************************************************************/


*38.

p.202

用pointer玩array會快些

example:


 int   array[10], a;
            for( a = 0; a < 10; a += 1 )
                  array[a] = 0;
 

To evaluate this subscript, the compiler inserts instructions in the program to take the value of a and multiply it by the size of an integer (say, four). This multiplication takes both space and time.


-----------------------


  int   array[10], *ap;
            for( ap = array; ap < array + 10; ap++ )
                  *ap = 0;


The multiplication is still in here somewhere, even though there is no longer any subscript. Look closely now and see if you can find it.
The multiplication is now performed in the adjustment step of the for statement; the value one must be scaled to the size of an integer before it is added to the pointer. But there is a big difference here: the same two values (1 × 4) are multiplied each time through the loop. As a result, this multiplication is performed once at compile time—the program now contains an instruction to add four to the pointer. No multiplications are performed at run time.


/********************************************************************/


  39.

P.210

int a[5];
int *b;


the declarations the expression *a is perfectly legal, but the expression *b is not. *b will access some indeterminate location in memory or cause the program to terminate. On the other hand, the expression b++ will compile, but a++ will not because the value of a is a constant.


/********************************************************************/


*40.

p.219

int matrix [3] [10];

matrix  <- "pointer to an array of ten integers"

matrix <- it points to first row == matrix[0][0]

*(matrix+1) <- it points to second row == point to matrix[1][0]

*(matrix+1)+5 <- == point to matrix[1][5]


/********************************************************************/


41.

P.222

int (*p)[10] ;


- Subscripts have a higher precedence than indirection, but the parentheses surrounding the indirection force it to go first. So p is a pointer to something, but to what?

- p is a pointer to an array of ten integers.

--------------

int matrix[3][10];

p=matrix; // makes p point to first row of matrix

-------------


      int   *pi = &matrix[0][0];
      int   *pi = matrix[0];

both are legal


 -----------


If you intend to perform any arithmetic with the pointer, avoid this kind of declaration: 

      int   (*p)[] = matrix
 
p is still a pointer to an array of integers, but the array size is missing. Integers involved in pointer arithmetic with this variable will be scaled by the size of an empty array (that is, multiplied by zero), which is probably not what you had in mind. Some compilers catch this error and some donʹt.


/********************************************************************/


42.

P.223


int   vector[10];
            ...
            func1( vector );
The type of the argument vector is a pointer to an integer, so func1 can be prototyped in either of the following ways:
            void func1( int *vec );
            void func1( int vec[] );
 
 --------------


  int   matrix[3][10];
            ...
            func2( matrix );

 The type of the argument matrix is a pointer to an array of ten integers, so func2 can be prototyped in either of the following ways:

            void func2( int (*mat)[10] );
            void func2( int mat[][10] );


 **
The key here is that the compiler must know the sizes of the second and subsequent dimensions in order to evaluate subscripts, thus the prototype must declare these dimensions. The size of the first dimension isnʹt needed because it is not used in the calculation of subscripts.


------


Specifically, it is incorrect to prototype func2 like this: 
    void func2(int **mat);


This example declares mat to be a pointer to a pointer to an integer, which is not at all the same thing as a pointer to an array of ten integers. 



/********************************************************************/


 43.

P. 227


 int   *api[10];
 api is an array of pointers to integers


Where would you ever use an array of pointers? Here is one example:
      char        const *keyword[] = {
                  "do",
                  "for",
                  "if",
                  "register",
                  "return",
                  "switch",
                  "while"
      };

//test
    printf("%lu\n", sizeof(keyword));
    printf("%lu\n", sizeof(keyword[0]));
    printf("%lu\n", sizeof(keyword[2]));
    printf("%lu\n", sizeof(keyword[3]));// result
56
8
8
8
// comment
在mac的gcc測試下,
sizeof(char) = 1 ,  sizeof(char *) = 8.
sizeof(int)=4 , sizeof(int*) = 8.


Example:

include <string.h>
  
char        const *keyword[] = {
                  "do",
                  "for",
                  "if",
                  "register",
                  "return",
                  "switch",
                  "while"
      };
      #define     N_KEYWORD
                  ( sizeof( keyword ) / sizeof( keyword[0] ) )

 
 

int
lookup_keyword( char const * const desired_word,

    char const *keyword_table[], int const size )
{

}



char  const **kwp;     // kwp 要const, 因為準備指向const pointer array

/*
** For each word in the table ...
*/
for( kwp = keyword_table; kwp < keyword_table + size; kwp++ )

      /*
      ** If this word matches the one we're looking for,
      ** return its position in the table.
      */
      if( strcmp( desired_word, *kwp ) == 0 )

            return kwp - keyword_table;

/*
** Not found.
*/
return -1;


// comment
sizeof( keyword ) gives the number of bytes in the entire array, and sizeof( keyword[0] ) is the number of bytes in one element. 


We could also store the keywords in a matrix, like this:
      char        const keyword[][9] = {
                  "do",
                  "for",
                  "if",
                  "register",
                  "return",
                  "switch",
                  "while"
};



- Notice the difference in the amount of memory used. The matrix looks inefficient because every row must be long enough to store the longest keyword. But it does not need any pointers. On the other hand, the array of pointers takes space, but each of the string literals is only as long as it needs to be.
- but the matrix is more compact because there is no space needed for pointers. 

-----------------------------------------
P. 231
      char     const *keyword[] = {
                  "do",
                  "for",
                  "if",
                  "register",
                  "return",
                  "switch",
                  "while"
                 NULL 
}; 

 NULL identify the end of array , without using size
 like: 
  for( kwp = keyword;  *kwp!=NULL ; kwp++); 



/********************************************************************/
 

沒有留言:

張貼留言