Changes to Answers to Frequently Asked Questions (FAQ) on comp.lang.c

Steve Summit scs at adam.mit.edu
Wed Aug 1 14:02:06 AEST 1990


This article contains the changes between the previous posting of
the frequently-asked questions list (July 18) and the new one
(coming up next).  (These diffs have been edited for readability
and are not suitable for the patch program.)

178,179c166,167
<     doing so sends the wrong stylistic message.  (The ANSI #definition
<     of NULL is allowed to be (void *)0, which will not work in non-
---
>     doing so sends the wrong stylistic message.  (ANSI allows the
>     #definition of NULL to be (void *)0, which will not work in non-

301a286,291
> 10. But I once used a compiler that wouldn't work unless NULL was used.
> 
> A:  This compiler was broken.  In general, making decisions about a
>     language based on the behavior of one particular compiler is likely
>     to be counterproductive.

416c406,410
<     formal argument declarations, nowhere else.
---
>     formal parameter declarations, nowhere else.  If this conversion
>     confuses you, don't use it; many people have concluded that the
>     confusion it causes outweighs the small advantage of having the
>     declaration "look like" the call and/or the uses within the
>     function.

446a441,528
> 17. My compiler complained when I passed a two-dimensional array to a
>     routine expecting a pointer to a pointer.
> 
> A:  The rule by which arrays decay into pointers is not applied
>     recursively.  An array of arrays (i.e. a two-dimensional array in C)
>     decays into a pointer to an array, not a pointer to a pointer.
>     Pointers to arrays are confusing, and it is best to avoid them.
>     (The confusion is heightened by incorrect compilers, including some
>     versions of pcc and pcc-derived lint's, which incorrectly accept
>     assignments of multi-dimensional arrays to multi-level pointers.)
>     If you are passing a two-dimensional array to a function:
> 
>          int array[YSIZE][XSIZE];
>          f(array);
> 
>     the function's declaration should match:
>          f(int a[][XSIZE]) {...}
>     or
>          f(int (*a)[XSIZE]) {...}
> 
>     In the first declaration, the compiler performs the usual implicit
>     rewriting of "array of array" to "pointer to array;" in the second
>     form the pointer declaration is explicit.  The called function does
>     not care how big the array is, but it must know its shape, so the
>     "column" dimension XSIZE must be included.  In both cases the number
>     of "rows" is irrelevant, and omitted.
> 
>     If a function is already declared as accepting a pointer to a
>     pointer, an intermediate pointer would need to be used when
>     attempting to call it with a two-dimensional array:
> 
>          int *ip = &a[0][0];
>          g(&ip);
>          ...
>          g(int **ipp) {...}
> 
>     Note that this usage is liable to be misleading (if not incorrect),
>     since the array has been "flattened" (its shape has been lost).
> 
> 18. How do I declare a pointer to an array?
> 
> A:  Usually, you don't want one.  Think about using a pointer to one of
>     the array's elements instead.  Arrays of type T decay into pointers
>     to type T, which is convenient; subscripting or incrementing the
>     resultant pointer accesses the individual members of the array.
>     True pointers to arrays, when subscripted or incremented, step over
>     entire arrays, and are generally only useful when operating on
>     multidimensional arrays.  (See the question above.)
> 
> 19. How can I dynamically allocate a multidimensional array?
> 
> A:  It is usually best to allocate an array of pointers, and then
>     initialize each pointer to a dynamically-allocated "row." The
>     resulting "ragged" array often saves space, although it may not be
>     contiguous in memory as a real array would be.
> 
>          int **array = (int **)malloc(nrows * ncolumns * sizeof(int *));
>          for(i = 0; i < nrows; i++)
>                  array[i] = (int *)malloc(ncolumns * sizeof(int));
> 
>     (In "real" code, of course, malloc's return value should be
>     checked.)
> 
>     You can keep the array's contents contiguous, while losing the
>     ability to have rows of varying and different lengths, with a bit of
>     explicit pointer arithmetic:
> 
>          int **array = (int **)malloc(nrows * ncolumns * sizeof(int *));
>          array[0] = (int *)malloc(nrows * ncolumns * sizeof(int));
>          for(i = 1; i < nrows; i++)
>                  array[i] = array[0] + i * ncolumns;
> 
>     In either case, the elements of the dynamic array can be accessed
>     with normal-looking array subscripts: array[i][j].
> 
>     If the double indirection implied by the above scheme is for some
>     reason unacceptable, you can simulate a two-dimensional array with a
>     single, dynamically-allocated one-dimensional array:
> 
>          int *array = (int *)malloc(nrows * ncolumns * sizeof(int));
> 
>     However, you must now perform subscript calculations manually,
>     accessing array[i, j] with array[i * ncolumns + j].  (A macro can
>     hide the explicit calculation, but invoking it then requires
>     parentheses and commas which don't look exactly like
>     multidimensional array subscripts.)

471c553,554
<     value 4.
---
>     value 4.  ANSI allows compilers to reject code which contains such
>     ambiguous or undefined side effects.

476c559
< 18. But what about the &&, ||, and ?: operators?
---
> 21. But what about the &&, ||, ?:, and comma operators?

549a633,635
>     (In this case, it would be clearest to change the old-style
>     definition to use double as well).

660c745,746
<     Note the cast on the last argument.
---
>     Note the cast on the last argument.  (Also note that the caller must
>     free the returned, malloc'ed storage.)

713a799,804
> 31. How can I write a function analogous to scanf?
> 
> A:  Unfortunately, vscanf and the like are not standard.  You're on your
>     own.

794a885,907
> 35. You can't use dynamically-allocated memory after you free it, can
>     you?
>
> A:  No.  Some early man pages for malloc stated that the contents of
>     freed memory was "left undisturbed;" this ill-advised guarantee is
>     not universal and is not required by ANSI.
> 
>     Few programmers would use the contents of freed memory deliberately,
>     but it is easy to do so accidentally.  Consider the following
>     (correct) code for freeing a singly-linked list:
> 
>          struct list *listp, *nextp;
>          for(listp = base; listp != NULL; listp = nextp) {
>                  nextp = listp->next;
>                  free((char *)listp);
>          }
> 
>     and notice what would happen if the more-obvious loop iteration
>     expression listp = listp->next were used, without the temporary
>     nextp pointer.

885,889c1000,1004
<          #define offsetof(type, mem) ((size_t) \
<                  ((char *)&(((type) *) 0)->mem - (char *)&(((type) *) 0)))
<
<     This implementation is not 100% portable; some compilers may refuse
<     to accept it.
---
>          #define offsetof(type, mem) ((size_t) \
>                  ((char *)&((type *) 0)->mem - (char *)((type *) 0)))
>
>     This implementation is not 100% portable; some compilers may
>     legitimately refuse to accept it.

1125a1239,1244
>     Operating system specific questions are not appropriate for
>     comp.lang.c .  Several common questions are answered in frequently-
>     asked questions postings in the comp.unix.questions and
>     comp.sys.ibm.pc newsgroups.

1265a1382,1391
> 62. Where can I get copies of all these public-domain programs?
> 
> A:  If you have access to Usenet, see the regular postings in the
>     comp.sources.unix and comp.sources.misc newsgroups, which describe,
>     in some detail, the archiving policies and how to retrieve copies.
>     Otherwise, you can try anonymous ftp and/or uucp from a central,
>     public-spirited site, such as uunet.uu.net, but this article cannot
>     track or list all of the available sites and how to access them.



More information about the Comp.lang.c mailing list