I have a comparison function for use in scandir
or qsort
to sort an array of struct dirent *
s by access date. S
is the directory path of the directory whose files are being sorted, and SavesLen
is strlen(S)
.
static int Q(const struct dirent **const First, const struct dirent **const Second) {
const char *const FirstName = (*First)->d_name, *const SecondName = (*Second)->d_name, *const Name[] = {FirstName, SecondName};
const unsigned short FirstLen = (unsigned short)strlen(FirstName), SecondLen = (unsigned short)strlen(SecondName), Len[] = {FirstLen, SecondLen};
char File[SavesLen+Len[FirstLen < SecondLen]+2], *CurrPtr = memcpy(File, S, SavesLen)+SavesLen;
*CurrPtr++ = '/';
time_t Time[2];
for (unsigned char I = 0; I < 2; I++) {
memcpy(CurrPtr, Name[I], Len[I]);
struct stat Stat;
if (stat(File, &Stat)){
return 0;
}
Time[I] = Stat.st_atimespec.tv_sec;
}
return Time[1]-(*Time);
}
Sorry for being obsessed with microoptimizations, but I'm looking to improve this.
S
and SavesLen
are both global variables defined and declared and initialized elsewhere. Is there a way to take advantage of local scopes to delete some of the memory earlier? Are there other improvements to be made? Thanks ahead of time.
An answerer pointed out that char File[SavesLen+Len[FirstLen > SecondLen]+2]
is extremely hard to read. So here's why I do it that way. There are 2 files, and I need to check the access time of both of them. Rather than creating a path for each one, I'm reusing the same path, to minimize the number of VLA declarations and the number of memcpy()
calls. Now let's break it down for you. char File[...]
is a VLA declaration. The size is SavesLen
plus the larger size of the 2 files, plus 2, for the /
and null character. So what the heck is Len[FirstLen > SecondLen]
? The reason why it's confusing is because I'm treating booleans like integers, and being weakly typed, C lets me do that. Len
is an array so it will either be indexed by 0 or 1 (the 2 boolean values) depending on which one is bigger, because FirstLen > SecondLen
will either evaluate to 0 or 1.
It seems the answerer understands, but in case there are others confused. I do agree that there was a bug, and that's because it used to be a ternary and I forgot to switch the values.
dirent
. Have you profiled your code to know that his is actually a bottleneck? \$\endgroup\$scandir
.struct dirent
is defined in<dirent.h>
. I don't think it has to be spelled out here. \$\endgroup\$