I expect I can do something like this:
int i = 0;
until (i == 2){
printf("yes\n");
i++;
}
Without telling detail about what until does, I'm sure reader know what is the algorithm from code above. Yes I know I can just use while(!condition){}.
The output will be:
yes
yes
So is it possible that I can achieve my goal?
I feel macro able to do this with define or something else. But I'm lack of knowledge about preprocessing directive syntax in C
#define until <what should I fill here>
Edit:
Many people triggered from what am I doing. I'm sorry for if I bother you guys. Don't worry, this syntax is just for my self only. So I hope I don't bother code reader who accidentally read my code or C priest.
First of all, and I can't stress this enough: making your own secret, private language using function-like macros is a cardinal sin in C. It is perhaps the worst thing you can ever do.
Why? Because other people reading your code are expected to know C. They are however not expected to know your secret private macro language. Furthermore, they have absolutely no interest in learning your secret private macro language.
So please never do things like this in real programs.
That being said, you pretty much already answered the question yourself:
#define until(condition) while(!(condition))
Note that condition, being a function-like macro parameter, should be placed inside a parenthesis. This prevents accidental operator precedence bugs. For example if the caller passes until(i + 1) then you want it to loop while(!(i+1)) and not while(!i + 1).
From Expert C Programming:
Macro use is best confined to naming literal constants,
shorthand for a few well-chosen constructs. Define the macro name all
in capitals so that, in use, it's instantly clear it's not a function
call. Shun any use of the C preprocessor that modifies the underlying
language so that it's no longer C.
Re: "I'm sure reader know what is the algorithm from code above."
No, it would confuse one even more as the keyword until is not part of the C language. It doesn't take much to type a few extra characters.
That being said, you could do:
#define until(condition) while(!(condition))
Compile your program with:
gcc -E -nostdinc main.c
to see what changes the preprocessor made.
But it would still be an abomination, and not something one would condone.
Using until is useful in select cases.
Sometimes an algorithm or software contract uses until in its definition, so it is good to see that match in code.
Yet re-writing language semantics adds confusion and maintenance costs.
Consider a comment when until is needed.
int i = 0;
// until (i == 2) {
while (i != 2) {
printf("yes\n");
i++;
}
Yes, you can use define for that. See the following example for the macro definition
#include <stdio.h>
#define until(x) while(!(x))
int main() {
int i = 0;
until (i == 2){
printf("iteration %d\n", i);
i++;
}
return 0;
}
If you run it, the output would be
iteration 0
iteration 1
I don't know why you would do this, until is a mostly abandoned keyword for a reason. But this should work:
#define until(cond) while (!(cond))
Related
I haven't included any code because it's not important to my question, but say I have a statement like if (g_sound == 1){printf("\a");} (of course I am just using a shorter example), how could I use this code all over my program while not having so much repetitiveness? Is there some type of variable which you could link to and have the code in that variable executed? So that half my code isn't the same thing over and over again... All help is much appreciated!
UPDATE: Thank you all for your helpful comments, I figured out that using a function would be the most optimal since it is a 20 line code I need to have executed! Thanks once again!
If the statement is really that simple (or at least optimal) then use a macro:
#define THIS_IS_NOT_A_FUNCTION(X) if (x == 1){ printf ("\a");}
Then the macro is used like this:
// do some tedious task that I can't be bother typing out fully:
THIS_IS_NOT_A_FUNCTION(g_sound);
As David C. Rankin pointed out in his comment, macros are expanded to their defined value pre-compile time so don't have the overhead of calling a function. The downside is that the code can become unreadable if macros are used too liberally.
If the statement is a complex operation it may pay to write a function and call that.
Here's a formal grammar brain teaser (maybe :P)
I'm fairly certain there is no context where the character sequence => may appear in a valid C program (except obviously within a string). However, I'm unable to prove this to myself. Can you either:
Describe a method that I can use for an arbitrary character sequence to determine whether it is possible in a valid C program (outside a string/comment). Better solutions require less intuition.
Point out a program that does this. I have a weak gut feeling this could be undecidable but it'd be great if I was wrong.
To get your minds working, other combos I've been thinking about:
:- (b ? 1:-1), !? don't think so, ?! (b ?!x:y), <<< don't think so.
If anyone cares: I'm interested because I'm creating a little custom C pre-processor for personal use and was hoping to not have to parse any C for it. In the end I will probably just have my tokens start with $ or maybe a backquote but I still found this question interesting enough to post.
Edit: It was quickly pointed out that header names have almost no restrictions so let me amend that I'm particularly interested in non-pre-processor code, alternatively, we could consider characters within the <> of #include <...> as a string literal.
Re-edit: I guess macros/pre-processor directives beat this question any which way I ask it :P but if anyone can answer the question for pure (read: non-macro'd) C code, I think it's an interesting one.
#include <abc=>
is valid in a C program. The text inside the <...> can be any member of the source character set except a newline and >.
This means that most character sequences, including !? and <<<, could theoretically appear.
In addition to all the other quibbles, there are a variety of cases involving macros.
The arguments to a macro expansion don't need to be syntactically correct, although of course they would need to be syntactically correct in the context of their expansion. But then, they might never be expanded:
#include <errno.h>
#define S_(a) #a
#define _(a,cosmetic,c) [a]=#a" - "S_(c)
const char* err_names[] = {
_(EAGAIN, =>,Resource temporarily unavailable),
_(EINTR, =>,Interrupted system call),
_(ENOENT, =>,No such file or directory),
_(ENOTDIR, =>,Not a directory),
_(EPERM, =>,Operation not permitted),
_(ESRCH, =>,No such process),
};
#undef _
const int nerr = sizeof(err_names)/sizeof(err_names[0]);
Or, they could be used but in stringified form:
#define _(a,b,c) [a]=#a" "S_(b)" "S_(c)
Note: Why #a but S_(c)? Because EAGAIN and friends are macros, not constants, and in this case we don't want them to be expanded before stringification.
/*=>*/
//=>
"=>"
'=>'
I was looking for a macro that will resemble the with-construct.
The usage should be something like:
with (lock(&x), unlock(&x)) {
...
}
It might be useful for some other purposes.
I came up with this macro:
#define __with(_onenter, _onexit, v) \
for (int __with_uniq##v=1; __with_uniq##v > 0; )\
for (_onenter; __with_uniq##v > 0; _onexit) \
while (__with_uniq##v-- > 0)
#define _with(x, y, z) __with(x, y, z)
#define with(_onenter, _onexit) _with(_onenter, _onexit, __COUNTER__)
It has 3 nested loops because it should:
Initialize loop counter (C99 only, of course)
Possibly initialize variable _onenter (such as with (int fd=open(..), close(fd)))
Allow break inside the code block. (continue is allowed too. And the macro could be adjusted to assert() it out)
I used it on the code for the XV6 OS and it seems quite useful.
My question is - what are the worst problems with such a macro? I mean, besides the mere usage of a C macro (especially one that implements new control-flow construct).
So far have found these drawbacks / problems:
No support for return or goto (but it can save some gotos in kernel code)
No support for errors (such as fd < 0). I think this one is fixable.
gnu89 / c99 and above only (loop counter. the unique variable trick is not necessary)
Somewhat less efficient than simple lock-unlock. I believe it to be insignificant.
Are there any other problems? Is there a better way to implement similar construct in C?
That macro scares me. I'd prefer the traditional approach using gotos.
That approach is primitive, but most C programmers are familiar with the pattern and if they're not, they can understand it by reading the local code. There is no hidden behavior. As a consequence, it's pretty reliable.
Your macro is clever, but it would be new to most everybody and it comes with hidden gotchas. New contributors would have to be thought rules such as "don't return or goto out of a with block" and "break will break out of the with block, not out of the surrounding loop". I fear mistakes would be common.
The balance would shift if you could add warnings for misuses of this construct to the compiler. With clang, that seems to be an option. In this case, misuses would be detected and your code would remain portable to other compilers.
If you're willing to restrict yourself to GCC and Clang, you can use the cleanup attribute. That would make your example look like this:
lock_t x = NULL __attribute__((cleanup(unlock)));
lock(&x);
And unlock will be called with a pointer to the variable when it goes out of scope. This is integrates with other language features like return and goto, and even with exceptions in mixed C/C++ projects.
I have some experience in programming in C but I would not dare to call myself proficient.
Recently, I encountered the following macro:
#define CONST(x) (x)
I find it typically used in expressions like for instance:
double x, y;
x = CONST(2.0)*y;
Completely baffled by the point of this macro, I extensively researched the advantages/disadvantages and properties of macros but still I can not figure out what the use of this particular macro would be. Am I missing something?
As presented in the question, you are right that the macro does nothing.
This looks like some artificial structure imposed by whoever wrote that code, maybe to make it abundantly clear where the constants are, and be able to search for them? I could see the advantage in having searchable constants, but this is not the best way to achieve that goal.
It's also possible that this was part of some other macro scheme that either never got implemented or was only partially removed.
Some (old) C compilers do not support the const keyword and this macro is most probably a reminiscence of a more elaborate sequence of macros that handled different compilers. Used like in x = CONST(2.0)*y; though makes no sense.
You can check this section from the Autoconf documentation for more details.
EDIT: Another purpose of this macro might be custom preprocessing (for extracting and/or replacing certain constants for example), like Qt Framework's Meta Object Compiler does.
There is absolutely no benefit of that macro and whoever wrote it must be confused. The code is completely equivalent to x = 2.0*y;.
Well this kind of macro could actually be usefull when there is a need to workaround the macro expansion.
A typical example of such need is the stringification macro. Refer to the following question for an example : C Preprocessor, Stringify the result of a macro
Now in your specific case, I don't see the benefit appart from extreme documention or code parsing purposes.
Another use could be to reserve those values as future function invocations, something like this:
/* #define CONST(x) (x) */
#define CONST(x) some_function(x)
// ...
double x, y;
x = CONST(2.0)*y; // x = some_function(2.0)*y;
Another good thing about this macro would be something like this
result=CONST(number+number)*2;
or something related to comparisons
result=CONST(number>0)*2;
If there is some problem with this macro, it is probably the name. This "CONST" thing isn't related with constants but with some other thing. It would be nice to look for the rest of the code to know why the author called it CONST.
This macro does have the effect of wrapping parenthesis around x during the macro expansion.
I'm guessing someone is trying to allow for something along the lines of
CONST(3+2)*y
which, without the parens, would become
3+2*y
but with the parens becomes
(3+2)*y
I seem to recall that we had the need for something like this in a previous development lifetime.
Having been writing Java code for many years, I was amazed when I saw this C++ statement:
int a,b;
int c = (a=1, b=a+2, b*3);
My question is: Is this a choice of coding style, or does it have a real benefit? (I am looking for a practicle use case)
I think the compiler will see it the same as the following:
int a=1, b=a+2;
int c = b*3;
(What's the offical name for this? I assume it's a standard C/C++ syntax.)
It's the comma operator, used twice. You are correct about the result, and I don't see much point in using it that way.
Looks like an obscure use of a , (comma) operator.
It's not a representative way of doing things in C++.
The only "good-style" use for the comma operator might be in a for statement that has multiple loop variables, used something like this:
// Copy from source buffer to destination buffer until we see a zero
for (char *src = source, *dst = dest; *src != 0; ++src, ++dst) {
*dst = *src;
}
I put "good-style" in scare quotes because there is almost always a better way than to use the comma operator.
Another context where I've seen this used is with the ternary operator, when you want to have multiple side effects, e.g.,
bool didStuff = DoWeNeedToDoStuff() ? (Foo(), Bar(), Baz(), true) : false;
Again, there are better ways to express this kind of thing. These idioms are holdovers from the days when we could only see 24 lines of text on our monitors, and squeezing a lot of stuff into each line had some practical importance.
Dunno its name, but it seems to be missing from the Job Security Coding Guidelines!
Seriously: C++ allows you to a do a lot of things in many contexts, even when they are not necessarily sound. With great power comes great responsibility...
This is called 'obfuscated C'. It is legal, but intended to confuse the reader. And it seems to have worked. Unless you're trying to be obscure it's best avoided.
Hotei
Your sample code use two not very well known by beginners (but not really hidden either) features of C expressions:
the comma operator : a normal binary operator whose role is to return the last of it's two operands. If operands are expression they are evaluated from left to right.
assignment as an operator that returns a value. C assignment is not a statement as in other languages, and returns the value that has been assigned.
Most use cases of both these feature involve some form of obfuscation. But there is some legitimate ones. The point is that you can use them anywhere you can provide an expression : inside an if or a while conditional, in a for loop iteration block, in function call parameters (is using coma you must use parenthesis to avoid confusing with actual function parameters), in macro parameter, etc.
The most usual use of comma is probably in loop control, when you want to change two variables at once, or store some value before performing loop test, or loop iteration.
For example a reverse function can be written as below, thanks to comma operator:
void reverse(int * d, int len){
int i, j;
for (i = 0, j = len - 1 ; i < j ; i++, j--){
SWAP(d[i], d[j]);
}
}
Another legitimate (not obfuscated, really) use of coma operator I have in mind is a DEBUG macro I found in some project defined as:
#ifdef defined(DEBUGMODE)
#define DEBUG(x) printf x
#else
#define DEBUG(x) x
#endif
You use it like:
DEBUG(("my debug message with some value=%d\n", d));
If DEBUGMODE is on then you'll get a printf, if not the wrapper function will not be called but the expression between parenthesis is still valid C. The point is that any side effect of printing code will apply both in release code and debug code, like those introduced by:
DEBUG(("my debug message with some value=%d\n", d++));
With the above macro d will always be incremented regardless of debug or release mode.
There is probably some other rare cases where comma and assignment values are useful and code is easier to write when you use them.
I agree that assignment operator is a great source of errors because it can easily be confused with == in a conditional.
I agree that as comma is also used with a different meaning in other contexts (function calls, initialisation lists, declaration lists) it was not a very good choice for an operator. But basically it's not worse than using < and > for template parameters in C++ and it exists in C from much older days.
Its strictly coding style and won't make any difference in your program. Especially since any decent C++ compiler will optimize it to
int a=1;
int b=3;
int c=9;
The math won't even be performed during assignment at runtime. (and some of the variables may even be eliminated entirely).
As to choice of coding style, I prefer the second example. Most of the time, less nesting is better, and you won't need the extra parenthesis. Since the use of commas exhibited will be known to virtually all C++ programmers, you have some choice of style. Otherwise, I would say put each assignment on its own line.
Is this a choice of coding style, or does it have a real benefit? (I am looking for a practicle use case)
It's both a choice of coding style and it has a real benefit.
It's clearly a different coding style as compared to your equivalent example.
The benefit is that I already know I would never want to employ the person who wrote it, not as a programmer anyway.
A use case: Bob comes to me with a piece of code containing that line. I have him transferred to marketing.
You have found a hideous abuse of the comma operator written by a programmer who probably wishes that C++ had multiple assignment. It doesn't. I'm reminded of the old saw that you can write FORTRAN in any language. Evidently you can try to write Dijkstra's language of guarded commands in C++.
To answer your question, it is purely a matter of (bad) style, and the compiler doesn't careāthe compiler will generate exactly the same code as from something a C++ programmer would consider sane and sensible.
You can see this for yourself if you make two little example functions and compile both with the -S option.