Funny C Rules (And Low-Level Languages in general)
Moderator: InsideQC Admins
75 posts
• Page 1 of 5 • 1, 2, 3, 4, 5
Funny C Rules (And Low-Level Languages in general)
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.
4) And this:
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
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.
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.
2) \ + a new line. Line continuation even inside a quote.
3) And of course this is valid: const char *mystring = "Hello" "World";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) 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.
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?
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)
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.
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.
- jitspoe
- Posts: 217
- Joined: Mon Jan 17, 2005 5:27 am
Re: Funny C Rules (And Low-Level Languages in general)
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?
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)
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!
Blah?". They became much easier to read in the code.
I didn't know about the sizeof one. Nice find!
-

mankrip - Posts: 915
- Joined: Fri Jul 04, 2008 3:02 am
Re: Funny C Rules (And Low-Level Languages in general)
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).mankrip wrote:I didn't know about the sizeof one. Nice find!
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?
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)
Baker wrote: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).mankrip wrote:I didn't know about the sizeof one. Nice find!
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).
- jitspoe
- Posts: 217
- Joined: Mon Jan 17, 2005 5:27 am
Re: Funny C Rules (And Low-Level Languages in general)
I can't speak for Quake 2, but in Quake 1 pretty much.jitspoe wrote:Isn't that basically what the entity parsing code does? (In Quake2, anyway, not sure about the other engines).
The night is young. How else can I annoy the world before sunsrise?
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)
Arrays:
See: http://stackoverflow.com/questions/5073 ... in-c-and-c
- 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
We knew the words, we knew the score, we knew what we were fighting for
-

mh - Posts: 2292
- Joined: Sat Jan 12, 2008 1:38 am
Re: Funny C Rules (And Low-Level Languages in general)
That's crazy!
The night is young. How else can I annoy the world before sunsrise?
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)
I forgot that C allows you do this:
(I'm not advocating any of these arguably inadvisable things, I just want to be aware of them.)
- Code: Select all
struct Distance{ int feet; float inch; }d1,d2,sum;
(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?
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)
You don't see this often used:
x = 5, y = 4 is a single statement.
so this is legit
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.
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?
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)
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. 
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
We knew the words, we knew the score, we knew what we were fighting for
-

mh - Posts: 2292
- Joined: Sat Jan 12, 2008 1:38 am
Re: Funny C Rules (And Low-Level Languages in general)
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.
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?
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)
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?
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)
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.
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.
- ericw
- Posts: 92
- Joined: Sat Jan 18, 2014 2:11 am
75 posts
• Page 1 of 5 • 1, 2, 3, 4, 5
Who is online
Users browsing this forum: No registered users and 1 guest