Live data from Hacker News

Why does the C preprocessor interpret the word “linux” as the constant “1”?

stackoverflow.com

21–30 of 60 posts

Re: Why does the C preprocessor interpret the word “linux” as the constant “1”?

#21
post #13

And that's why, in my opinion, non capitalized macros are always evil (yes, I'm looking at you linux kernel). When I see a lowercase symbol used as a variable, I expect it's going to be some actual global variable. When I see a lower case symbol used like a function I expect it's an actual function. And then comes the day I want to take the address of the "function" and it fails. Or worse, I make a syntax error somew…

Yup. This is why in Rust macros have to end with a ! (and syntax highlighters know about this). This was a hard call, because it prevents using macros to create forms that look exactly like the built-in ones, but it prevents issues such as the one described in the OP.

Re: Why does the C preprocessor interpret the word “linux” as the constant “1”?

#22
post #13

And that's why, in my opinion, non capitalized macros are always evil (yes, I'm looking at you linux kernel). When I see a lowercase symbol used as a variable, I expect it's going to be some actual global variable. When I see a lower case symbol used like a function I expect it's an actual function. And then comes the day I want to take the address of the "function" and it fails. Or worse, I make a syntax error somew…

Yup. This is why in Rust macros have to end with a ! (and syntax highlighters know about this). This was a hard call, because it prevents using macros to create forms that look exactly like the built-in ones, but it prevents issues such as the one described in the OP.

But... the ability to use macros to create forms that look like "real" syntax is sort of the point. I don't think you can fix this with a language feature or style convention.

Metaprogramming is "dangerous" because the meta constructs don't (can't!) act like what they look liks. Metaprogramming is "great" because the meta constructs look like simple programming but have surprisingly deep behavior.

As I see it all you did was add a "!" to the confusion, honestly. People likely to get tripped up by e.g. the "address of macro" problem above are going to be no less confused by the extra syntax IMHO.

Re: Why does the C preprocessor interpret the word “linux” as the constant “1”?

#23
post #22

Earlier quoted context omitted.

Yup. This is why in Rust macros have to end with a ! (and syntax highlighters know about this). This was a hard call, because it prevents using macros to create forms that look exactly like the built-in ones, but it prevents issues such as the one described in the OP.

But... the ability to use macros to create forms that look like "real" syntax is sort of the point. I don't think you can fix this with a language feature or style convention. Metaprogramming is "dangerous" because the meta constructs don't (can't!) act like what they look liks. Metaprogramming is "great" because the meta constructs look like simple programming but have surprisingly deep behavior. As I see it all you…

When you see an exclamation point, you know that compile-time fishiness is happening. If you don't see it, you know that there's nothing fishy going on. You might not think that's useful, but I hardly see how it can add to the confusion.

For clarity I just want to note here that Rust macros are structural (like Scheme) rather than textual (like C).

Re: Why does the C preprocessor interpret the word “linux” as the constant “1”?

#24
post #13

And that's why, in my opinion, non capitalized macros are always evil (yes, I'm looking at you linux kernel). When I see a lowercase symbol used as a variable, I expect it's going to be some actual global variable. When I see a lower case symbol used like a function I expect it's an actual function. And then comes the day I want to take the address of the "function" and it fails. Or worse, I make a syntax error somew…

Yup. This is why in Rust macros have to end with a ! (and syntax highlighters know about this). This was a hard call, because it prevents using macros to create forms that look exactly like the built-in ones, but it prevents issues such as the one described in the OP.

Ah! That's great, I didn't know that. The more I hear about rust the more I like it. But then I'm reminded that it bakes garbage collection into the core language...

Oh well, perfection is no of this world.

Re: Why does the C preprocessor interpret the word “linux” as the constant “1”?

#25
post #5

If you're in the habit of writing "struct sockaddr_in sin;", you'll probably be tempted to write "struct sockaddr_un sun;". Just don't expect that code to compile on Solaris.

Is that just hardcoded into the preprocessor itself? Or is part of ANSI C. Wondering if the MS C++ compiler will do this well.

It's not and can be tuned using compiler options as mentioned in TFA. Definitely not standard.

Re: Why does the C preprocessor interpret the word “linux” as the constant “1”?

#27
post #13

And that's why, in my opinion, non capitalized macros are always evil (yes, I'm looking at you linux kernel). When I see a lowercase symbol used as a variable, I expect it's going to be some actual global variable. When I see a lower case symbol used like a function I expect it's an actual function. And then comes the day I want to take the address of the "function" and it fails. Or worse, I make a syntax error somew…

Yup. This is why in Rust macros have to end with a ! (and syntax highlighters know about this). This was a hard call, because it prevents using macros to create forms that look exactly like the built-in ones, but it prevents issues such as the one described in the OP.

That's not the original issue. The problem is that the compiler silently predefines an undocumented macro. If the compiler silently predefined an undocumented variable, type, or function called "linux" or "unix", that too can be a problem. E.g., if there were a global function linux() on Linux systems only and you tried to define a global variable linux in your code, you'd get an error, too.

The clean solution is to do what clang does and generate informative error messages. In the case of macros, by showing the macro expansion history. For example, the following (using __STDC__ instead of linux for portability):

  foo.c:2:7: error: expected identifier or '('
    int __STDC__ = 1;
        ^
  :159:18: note: expanded from here
  #define __STDC__ 1
Note that there can be other reasons to have macros that are syntactically different from functions and variables, but this isn't one of them.

Re: Why does the C preprocessor interpret the word “linux” as the constant “1”?

#28
post #24

Earlier quoted context omitted.

Yup. This is why in Rust macros have to end with a ! (and syntax highlighters know about this). This was a hard call, because it prevents using macros to create forms that look exactly like the built-in ones, but it prevents issues such as the one described in the OP.

Ah! That's great, I didn't know that. The more I hear about rust the more I like it. But then I'm reminded that it bakes garbage collection into the core language... Oh well, perfection is no of this world.

There's a project, zero.rs, that lets you have no runtime in rust. It's been shown that it's possible to make a simple kernel with it without too much pain. The disadvantage, of course, is that libraries will use garbage collection, and as soon as it's used, you get the runtime, so you can only use certain libraries designed for zero.rs, which causes fragmentation.

All this would happen if gc was in the std library anyway though.

Re: Why does the C preprocessor interpret the word “linux” as the constant “1”?

#29
post #28
post #24

Earlier quoted context omitted.

Ah! That's great, I didn't know that. The more I hear about rust the more I like it. But then I'm reminded that it bakes garbage collection into the core language... Oh well, perfection is no of this world.

There's a project, zero.rs, that lets you have no runtime in rust. It's been shown that it's possible to make a simple kernel with it without too much pain. The disadvantage, of course, is that libraries will use garbage collection, and as soon as it's used, you get the runtime, so you can only use certain libraries designed for zero.rs, which causes fragmentation. All this would happen if gc was in the std library a…

Fair enough. I just have to cross my fingers and hope the GC won't catch on then! :)

Re: Why does the C preprocessor interpret the word “linux” as the constant “1”?

#30
post #28
post #24

Earlier quoted context omitted.

Ah! That's great, I didn't know that. The more I hear about rust the more I like it. But then I'm reminded that it bakes garbage collection into the core language... Oh well, perfection is no of this world.

There's a project, zero.rs, that lets you have no runtime in rust. It's been shown that it's possible to make a simple kernel with it without too much pain. The disadvantage, of course, is that libraries will use garbage collection, and as soon as it's used, you get the runtime, so you can only use certain libraries designed for zero.rs, which causes fragmentation. All this would happen if gc was in the std library a…

Rust libraries rarely use GC. The standard library goes out of its way to avoid it wherever possible, while remaining safe.
Post reply on HN