Funny C Rules (And Low-Level Languages in general)

Discuss programming topics for the various GPL'd game engine sources.
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Funny C Rules (And Low-Level Languages in general)

Post by Baker »

1) // marks the beginning on a comment. It doesn't terminate a statement, obviously. But does terminate a preprocessor command like #define so C isn't entirely whitespace agnostic
2) \ + a new line. Line continuation even inside a quote.
const char *mystring = "Hello \
World";
3) And of course this is valid: const char *mystring = "Hello" "World";
4) And this:
#define otherstring "New"
const char *mystring = "Hello" otherstring "World";
5) Every line of code should be terminated with a new line. Although most compilers won't complain about it.
6) int x=016; // Decimal value is 14 because a leading zero makes something OCTAL
7) /* This comment is /* invalid */ because inline comments don't nest */
8 ) #define THAT(X) is ok. #define THAT (X) is not ok because of the extra space before the paren.
9) This 634L is a long, this 634u is unsigned and this 634ul is an unsigned long.
10) Every time I stopping using preprocessor stringification symbols # and ## for any length of time, I forget how they work again

Code: Select all

	#define ENUMDEF(_name,_default,_flags) \
		{ #_name	  , fc_##_name },
11) I suspect adding +1 to a float or a double with a maximum value will generate a floating-point overflow signal. I suspect doing the same for a byte, int32, etc doesn't.
11) As far as I know, all functions are type extern unless declared static. There is a real use for extern with functions, I just can't remember what it is. :D
12) "int j;" if inside a function, j is undefined. If outside a function, j = 0. But "static int j;" inside or outside a function are both 0. This is because inside
13) sizeof is an operator. It does not require parenthesis. int j; int k = sizeof j; int m = sizeof(j); // Both j and m will be 4 on pretty much any platform in 2015.
14) Preprocessor directives must be at the start of their own line (allowing for whitespace).
15) Arrays. You can do this: int my_numbers [] = { 4,5,6,7, }; Note the trailing comma after the last element.
16) Offsetof isn't a function. It is a really screwy macro! #define offsetof(s,m) (size_t)&(((s *)0)->m)
17) The C assert statement (which conditionally kicks out an error when debugging) expects NDEBUG to be defined in a release build.
Last edited by Baker on Fri Feb 27, 2015 12:07 am, edited 9 times in total.
The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
jitspoe
Posts: 217
Joined: Mon Jan 17, 2005 5:27 am

Re: Funny C Rules (And Low-Level Languages in general)

Post by jitspoe »

The "string" "combination" stuff is super useful:

A lame example, but:

#define GAME_NAME "MyTestGame"

const char *welcome_string = "Hello, and welcome to " GAME_NAME "! Enjoy your stay!"

If you have a string like this that frequently changes and is used all over (ex version/build ID), it can be a real time saver.
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Re: Funny C Rules (And Low-Level Languages in general)

Post by Baker »

I find the lack of preprocessor capabilities to do some light string manipulation a limitation, personally. To anything other than very light string concatenation is non-existent. With the stringify macro operators you can do some fairly interesting things, but the preprocessor directives required to pull it off end up being rather difficult to read :(
The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
mankrip
Posts: 924
Joined: Fri Jul 04, 2008 3:02 am

Re: Funny C Rules (And Low-Level Languages in general)

Post by mankrip »

I used the second one for all quit messages, as in "Blahblah.\n\n\
Blah?"
. They became much easier to read in the code.

I didn't know about the sizeof one. Nice find!
Ph'nglui mglw'nafh mankrip Hell's end wgah'nagl fhtagn.
==-=-=-=-=-=-=-=-=-=-==
Dev blog / Twitter / YouTube
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Re: Funny C Rules (And Low-Level Languages in general)

Post by Baker »

mankrip wrote:I didn't know about the sizeof one. Nice find!
I never thought about sizeof much until I ran across a interest rant by Linus Torvalds. I don't think sizeof had much to do with the rant, but he was calling someone ignorant in great detail because they were criticizing an alleged shortcoming in C without knowing too much about what the language was actually doing under the hood (or something like that ... been a while since I read it).

The much lesser known offsetof "function" isn't a function either, per se. But a macro:

#define offsetof(s,m) (size_t)&(((s *)0)->m)

offsetof tells the number of bytes into a struct. And lets you do things that are conventionally considered "evil", but really aren't like accessing variables inside a struct like an array.
The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
jitspoe
Posts: 217
Joined: Mon Jan 17, 2005 5:27 am

Re: Funny C Rules (And Low-Level Languages in general)

Post by jitspoe »

Baker wrote:
mankrip wrote:I didn't know about the sizeof one. Nice find!
I never thought about sizeof much until I ran across a interest rant by Linus Torvalds. I don't think sizeof had much to do with the rant, but he was calling someone ignorant in great detail because they were criticizing an alleged shortcoming in C without knowing too much about what the language was actually doing under the hood (or something like that ... been a while since I read it).

The much lesser known offsetof "function" isn't a function either, per se. But a macro:

#define offsetof(s,m) (size_t)&(((s *)0)->m)

offsetof tells the number of bytes into a struct. And lets you do things that are conventionally considered "evil", but really aren't like accessing variables inside a struct like an array.
Isn't that basically what the entity parsing code does? (In Quake2, anyway, not sure about the other engines).
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Re: Funny C Rules (And Low-Level Languages in general)

Post by Baker »

jitspoe wrote:Isn't that basically what the entity parsing code does? (In Quake2, anyway, not sure about the other engines).
I can't speak for Quake 2, but in Quake 1 pretty much.
The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
mh
Posts: 2292
Joined: Sat Jan 12, 2008 1:38 am

Re: Funny C Rules (And Low-Level Languages in general)

Post by mh »

Arrays:

Code: Select all

a[4]; // this is legal
4[a]; // and so is this!
See: http://stackoverflow.com/questions/5073 ... in-c-and-c
We had the power, we had the space, we had a sense of time and place
We knew the words, we knew the score, we knew what we were fighting for
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Re: Funny C Rules (And Low-Level Languages in general)

Post by Baker »

That's crazy!
The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Re: Funny C Rules (And Low-Level Languages in general)

Post by Baker »

I forgot that C allows you do this:

Code: Select all

struct Distance{ int feet; float inch; }d1,d2,sum;
I suspect C allows defining structs within structs and in unions and maybe within the arguments of function declarations.

(I'm not advocating any of these arguably inadvisable things, I just want to be aware of them.)
The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Re: Funny C Rules (And Low-Level Languages in general)

Post by Baker »

You don't see this often used:

x = 5, y = 4 is a single statement.

so this is legit
if (x == 1) x = 4, y = 3;
Also not seen frequently: x = b = c = 0. Interestingly enough, most operations go left to right, but clearly not here. I have heard that C doesn't guarantee left to right evaluation (except for short-circuiting logical operators like || and &&) even for something like 3 + 9 + 7. Left to right evaluation is a different thing than order of operator (multiplication before addition, etc.
The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
mh
Posts: 2292
Joined: Sat Jan 12, 2008 1:38 am

Re: Funny C Rules (And Low-Level Languages in general)

Post by mh »

Assignment in any sane world should always go right-to-left. The C assignment operator, strcpy, memcpy - all go right-to-left. Quake's VectorCopy (and other Vector* macros) have tripped me up more than once. :evil:
We had the power, we had the space, we had a sense of time and place
We knew the words, we knew the score, we knew what we were fighting for
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Re: Funny C Rules (And Low-Level Languages in general)

Post by Baker »

I don't like how those goes src, dst when memcpy, etc. are dst src.

I somethings get torn on whether a function should indicate success by returning 0 or non-zero ...

a) success should return 0 (like a main() or command line utility, and non-zero is an error)
b) success should return non-zero (true) and failure should return false.

Ultimately there is never a single right answer.
if (1 == 1) ... = returns 1;
if (strcmp/memcmp("red","red")) ... returns 0
The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Re: Funny C Rules (And Low-Level Languages in general)

Post by Baker »

Old K&R style C probably still works in Visual Studio. I've seen K&R looking C code occasionally when looking for algorithms or reading things published in the 1990s.

Code: Select all

int foo(a, p) 
    int a; 
    char *p; 
{ 
    return 0; 
}
The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
ericw
Posts: 92
Joined: Sat Jan 18, 2014 2:11 am

Re: Funny C Rules (And Low-Level Languages in general)

Post by ericw »

Yeah the
dest->foo = src->foo;
VectorCopy(src->pos, dest->pos);
thing is awful. Using "const" liberally could detect mixing up the order of VectorCopy, but usually in Quake both source and dest are mutable.

IMO the 0=success, 1=failure, or -1=less, 0=same, 1=greater stuff is horrible legacy style, but often you have to have no choice because you're using API's that use that. The right way is C++11's "enum class" which don't implicitly convert to int.
Post Reply