Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>What you are saying in your post is absolutely correct. I'd say that every C developer comes to exactly the same discovery and to exactly the same conclusion when (if) they reach certain level of proficiency with C language.</p> <p>When the specifics of your application area call for an array of specific fixed size (array size is a compile-time constant), the only proper way to pass such an array to a function is by using a pointer-to-array parameter</p> <pre><code>void foo(char (*p)[10]); </code></pre> <p>(in C++ language this is also done with references</p> <pre><code>void foo(char (&amp;p)[10]); </code></pre> <p>).</p> <p>This will enable language-level type checking, which will make sure that the array of exactly correct size is supplied as an argument. In fact, in many cases people use this technique implicitly, without even realizing it, hiding the array type behind a typedef name</p> <pre><code>typedef int Vector3d[3]; void transform(Vector3d *vector); /* equivalent to `void transform(int (*vector)[3])` */ ... Vector3d vec; ... transform(&amp;vec); </code></pre> <p>Note additionally that the above code is invariant with relation to <code>Vector3d</code> type being an array or a <code>struct</code>. You can switch the definition of <code>Vector3d</code> at any time from an array to a <code>struct</code> and back, and you won't have to change the function declaration. In either case the functions will receive an aggregate object "by reference" (there are exceptions to this, but within the context of this discussion this is true).</p> <p>However, you won't see this method of array passing used explicitly too often, simply because too many people get confused by a rather convoluted syntax and are simply not comfortable enough with such features of C language to use them properly. For this reason, in average real life, passing an array as a pointer to its first element is a more popular approach. It just looks "simpler".</p> <p>But in reality, using the pointer to the first element for array passing is a very niche technique, a trick, which serves a very specific purpose: its one and only purpose is to facilitate passing arrays of <em>different size</em> (i.e. run-time size). If you really need to be able to process arrays of run-time size, then the proper way to pass such an array is by a pointer to its first element with the concrete size supplied by an additional parameter</p> <pre><code>void foo(char p[], unsigned plen); </code></pre> <p>Actually, in many cases it is very useful to be able to process arrays of run-time size, which also contributes to the popularity of the method. Many C developers simply never encounter (or never recognize) the need to process a fixed-size array, thus remaining oblivious to the proper fixed-size technique.</p> <p>Nevertheless, if the array size is fixed, passing it as a pointer to an element</p> <pre><code>void foo(char p[]) </code></pre> <p>is a major technique-level error, which unfortunately is rather widespread these days. A pointer-to-array technique is a much better approach in such cases.</p> <p>Another reason that might hinder the adoption of the fixed-size array passing technique is the dominance of naive approach to typing of dynamically allocated arrays. For example, if the program calls for fixed arrays of type <code>char[10]</code> (as in your example), an average developer will <code>malloc</code> such arrays as</p> <pre><code>char *p = malloc(10 * sizeof *p); </code></pre> <p>This array cannot be passed to a function declared as</p> <pre><code>void foo(char (*p)[10]); </code></pre> <p>which confuses the average developer and makes them abandon the fixed-size parameter declaration without giving it a further thought. In reality though, the root of the problem lies in the naive <code>malloc</code> approach. The <code>malloc</code> format shown above should be reserved for arrays of run-time size. If the array type has compile-time size, a better way to <code>malloc</code> it would look as follows</p> <pre><code>char (*p)[10] = malloc(sizeof *p); </code></pre> <p>This, of course, can be easily passed to the above declared <code>foo</code></p> <pre><code>foo(p); </code></pre> <p>and the compiler will perform the proper type checking. But again, this is overly confusing to an unprepared C developer, which is why you won't see it in too often in the "typical" average everyday code.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload