Assignment 4 advice/faq

Written by Julie Zelenski

Design advice

Wise use of memory/pointers

Common questions about assign4


I don't know how to properly call scandir. Help!

Remember, the code to musl_scandir is given in the assignment writeup if you want to review its implementation to remind yourself of how the function uses its various parameters.

The man page for scandir also contains a short example program. Minor heads up: that example program happens to print the entries in reverse order which may not be what you want/expect. Be wary of dropping in code from the documentation without reviewing it first to know what you are getting and whether you will need to adapt it.

How do I declare a parameter/variable of function pointer type?

The syntax for this is a bit goopy. The name of the variable is buried in the middle of the declaration and you have to read from inside out. The declaration below says the variable c is a pointer to a function that takes two const void* parameters and returns an int.

int (*c)(const void *, const void *) = my_compare;

Making a typedef for the function pointer type is a nice way to clean this up. The typedef below establishes cmpfn_t as a nickname for int (*)(const void *, const void*). This typedef means you can now use cmpfn_t as the type for a variable, parameter, return type, in place of the longhand form.

typedef int (*cmpfn_t)(const void *, const void *);

cmpfn_t c = my_compare;

See your C reference or web search for more info on typedef. A neat online resource for unraveling complex C declarations is cdecl.org.

How do I resolve the compiler warning pointer of type void * used in arithmetic?

The pointer arithmetic expression pointer + n implicitly scales n by the size of the pointee before adding it to pointer. If pointer is a void*, its pointee size is unknown, and the compiler will squawk because it cannot apply the proper scaling. To perform pointer arithmetic on a void* you must first cast it to indicate the desired scaling. The typical approach is to cast to char* to get no scaling and then manually multiply yourself.

What is the difference between memcpy and memmove?

Both are optimized routines for copying a region of raw bytes. memcpy is expected to be somewhat efficient that memmove but requires that the source and destination regions are distinct, whereas memmove correctly handles if the regions overlap. Either can be used to write an entire sequential block of a memory in one call, which can be much more efficient that repeated calls to process the memory in smaller pieces.

My custom sanitycheck tests for mysort report mismatch due to re-ordering of equal lines. Is this a problem?

There is no required tie-breaker for equal lines, the spec allows mysort to print them in any order. But sanity check is looking for an exact match so you should construct your custom tests so as to not trip on spurious discrepancies. In grading, our tests will accept any valid reordering of equal lines.