-
Notifications
You must be signed in to change notification settings - Fork 560
C99
This page exists for "requirements gathering". Once we're done, this page will be replaced by finished documentation in blead.
For various reasons C99 took a long time to become widely available. We still can't rely on all of it (certainly not the parts C11 made optional) but there are several features we'd like to use, if we know they work everywhere.
To clearly document what we can use, we need to figure this out - in particular, the trade off between "supporting awkward compilers" and "useful".
Hence we need to figure out what we can use, so we can document this.
We already support/fake
- bool
- static inline
- static assert
(And even adding support for bool
more than a decade after C99, we hit compiler bugs for things like converting a pointer to a bool
, and bool
in ternaries. This stuff hasn't been battle tested widely.)
We already exceed C89 minimally required limits on
- line length after macro expansion
- cases in a switch statement
without problems, so we shouldn't worry about staying strictly within a C89 straight jacket for these.
For what we might need gcc 3.1 or later is fine. 19 year old gcc will be fine...
Whilst not the default,
-
xlc
on AIX officially got c99 support in July 2002 with version V6.0 ---qlanglvl=stdc99
- HP
aC/C++
references C99 support in documents from 2004 ---AC99
- VMS vendor compiler?
- MSVC since when?
Open questions are:
#include <stdio.h>
int main(int argc, char **argv) {
// Comment
puts("Built "
// Comment
"// comments");
return 0;
}
None have been clearly explained.
- vendor compiler on VMS?
AIX xlc-
HP-UX cc(at least with A.06.28.02) - first MSVC that supports this?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct greeting {
unsigned int len;
char message[];
};
int main(int argc, char **argv) {
const unsigned int len = strlen(argv[0]);
struct greeting *g = malloc(sizeof(struct greeting) + len + 1);
g->len = len;
memcpy(g->message, argv[0], len);
printf("Built flexible arrays (as %*s)\n", g->len, g->message);
return 0;
}
This is standards conformant, unlike the "unwarranted chumminess with the compiler" hack we currently use of
struct greeting {
unsigned int len;
char message[1];
};
However, we use that hack already, and it works. So what do we gain?
Also, (IIRC) flexible array members are not allowed within nested struct
s or union
s, whereas the hack we have works as the last member within nested aggregates.
vendor compiler on VMSAIX xlc-
HP-UX cc(at least with A.06.28.02) - first MSVC that supports this?
even if slow, and just for arithmetic and bitwise operators
#include <stdio.h>
int main(int argc, char **argv) {
unsigned long long hex = 18364758544493064720ULL;
unsigned long long big = 0x9e3779b97f4a7c15;
unsigned long small = 0x9e3779b7;
puts("Built 64 bit integer types");
printf("%llX >> 4 is %llX\n", hex, hex >> 4);
printf("%llX * %lX is %llX\n", big, small, big * small);
return 0;
}
- Certain calculations can be expressed directly
- vendor compiler on VMS?
AIX xlc-
HP-UX cc(at least with A.06.28.02) - first MSVC that supports this?
#include <stdio.h>
#include <stdarg.h>
void greet(char *file, unsigned int line, char *format, ...) {
va_list ap;
va_start(ap, format);
printf("I was called at %s %u to say: ", file, line);
vprintf(format, ap);
va_end(ap);
}
#define logged_greet(...) greet(__FILE__, __LINE__, __VA_ARGS__)
int main(int argc, char **argv) {
char *action = "Built";
char *source = "variadic macros";
logged_greet("%s %s\n", action, source);
logged_greet("argv[0] is %s\n", argv[0]);
return 0;
}
- very useful for making
sprintf
style defines actually DWIM with PERL_NO_CONTEXT
- vendor compiler on VMS?
AIX xlc-
HP-UX cc(at least with A.06.28.02) - first MSVC that supports this?
#include <stdio.h>
int main(int argc, char **argv) {
char *action;
action = "Built";
const char *source = "mixed declarations and code";
printf("%s %s\n", action, source);
return 0;
}
- Can directly reduce line count without reducing readability
- Can indirectly make it easier to use const
- We have some macros which introduce declarations - knowing the ordering conventions is a barrier to entry
vendor compiler on VMSAIX xlc-
HP-UX cc(at least with A.06.28.02) - first MSVC that supports this?
#include <stdio.h>
int main(int argc, char **argv) {
char *message = "Built declarations in for loops\n";
for (const char *p = message; *p; ++p) {
putchar(*p);
}
return 0;
}
- Can directly reduce line count without reducing readability
- Can indirectly make it easier to use const
vendor compiler on VMSAIX xlc-
HP-UX cc(at least with A.06.28.02) - first MSVC that supports this?
Beware - gcc 4.7 needed --std=c99
to compile this. Potentially --std=c99
might then warn about gcc-isms, so maybe --std=gnu99
would be better.
#include <stdio.h>
struct message {
char *action;
char *target;
};
void greet(struct message mcguffin) {
printf("%s %s\n", mcguffin.action, mcguffin.target);
}
int main(int argc, char **argv) {
struct message mcguffin = { .target = "member structure initialisers", .action = "Built" };
greet(mcguffin);
return 0;
}
- Clearer code.
- Less chance of errors.
- Structures can be re-ordered without makework.
Frustratingly these were only recently added to C++, so we couldn't use them in headers, even if we can use them elsewhere.
- vendor compiler on VMS?
AIX xlc-
HP-UX cc(at least with A.06.28.02) - first MSVC that supports this?
Beware - the test case is simplistic. It's quite possible there are bugs on some compilers once one tries to nest these. However, if we find these, it's:
- Doctor doctor, it hurts when I do this.
- Well, don't do that then.
and we use old-style syntax instead.
Nice that this feature is, the "lack of C++ support" might already be a big enough blocker to make it less than worthwhile.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char **argv) {
const unsigned int len = strlen(argv[0]);
char buffer[len];
memcpy(buffer, argv[0], len);
printf("Built variable length arrays (as %*s)\n", len, buffer);
return 0;
}
- avoids a call to
malloc
- avoids missing calls to
free
, particularly on error paths
C11 made this optional. Dammit.
vendor compiler on VMSAIX xlc-
HP-UX cc(at least with A.06.28.02) - first MSVC that supports this?