The code snippet below works as is but if I uncomment the first #define and comment the second the compiler complains about expecting a ')' at the assignment statement. Thought it might be wanting a cast but that did not help. Please point out my stupid oversight.
Thanks,
jh
//#define SMI_READ (0b10 << 10)
#define SMI_READ (0x2 << 10)
...
command |= SMI_READ;
In general, to answer a question like this we need to see the complete and unedited text of the error messages, and it also really helps if you provide a complete program that we can attempt to compile for ourselves. (It might seem to you that the error messages are useless, but often it's just that they only make sense if you know how to think like a compiler engineer.)
However, in this case, I can make a high-confidence guess, because the only difference between the two macros is that the one that doesn't work uses a binary number, 0b10, and the one that does work uses a hexadecimal number, 0x2. Binary numbers are not part of any version of the C standard, although they are a common extension. I therefore deduce that your compiler doesn't support them and is giving an unclear error message when it encounters them.
From C standard (http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf)
6.4.4.1 Integer constants
...
octal-constant:
0
octal-constant octal-digit
...
hexadecimal-prefix: one of
0x 0X
No other prefixes are described, especially nothing which would cover 0b10.
Related
I looked ANSI C grammar (lex).
And this is octal digit regex
0{D}+{IS}? { count(); return(CONSTANT); }
My question is why do they accept something like 0898?
It's not an octal digit.
So i thought they would consider that, but they just have wrote like that.
Could you explain why is that? Thank you
You want reasonable, user-friendly error messages.
If your lexer accepts 0999, you can detect an illegal octal digit and output a reasonable message:
int x = 0999;
^
error: illegal octal digit, go back to school
If it doesn't, it will parse this as two separate tokens 0 and 999 and pass them to the parser. The resulting error messages could be quite confusing.
int x = 0999;
^
error: expected ‘,’ or ‘;’ before numeric constant
The invalid program is rejected either way, as it should, however the ostensibly incorrect lex grammar does a better job with error reporting.
This demonstrates that practical grammars built for tools such as lex or yacc do not have to correspond exactly to ideal grammars found in language definitions.
Keep in mind that this is only syntax, not semantic.
So it is sufficient to detect "Cannot be anything but a constant.".
It is not necessary (yet) to detect "A correct octal constant.".
Note that it does not even make a difference between octal, decimal, hexadecimal. All of them register as "CONSTANT".
The grammar you repeatedly link to in your questions was produced in 1985, 4 years prior to the publication of the first C standard revision in 1989.
That is not the grammar that was published in the standard of 1989, which clearly uses
octal-constant:
0
octal-constant octal-digit
octal-digit: one of
0 1 2 3 4 5 6 7
Even then, that Lex grammar is sufficient for tokenizing a valid program.
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 am trying to implement the standard xor swap algorithm as a C macro.
I have two versions of the macro. One that doesn't worry about the types and one that attempts to cast everything to an integer.
Here are the macro's
#define XOR_SWAP(a,b) ((a)^=(b),(b)^=(a),(a)^=(b))
#define LVALUE_CAST(type,value) (*((type)*)&(value))
#define XOR_CAST_SWAP(type,a,b) (LVALUE_CAST((type),(a))=(type)(a)^(type)(b),LVALUE_CAST((type),(b))=(type)(b)^(type)(a),LVALUE_CAST((type),(a))=(type)(a)^(type)(b))
I know it's a pain to read the one with a cast, but your efforts are appreciated.
The error that I'm getting is:
some_file.c(260,3): expected expression before ')' token
Now, I'm looking at it but I still can't figure out where my problem lies.
I've even used the -save-temps option to capture the preprocessor output and the line looks like this:
((*(((intptr_t))*)&((Block1)))=(intptr_t)(Block1)^(intptr_t)(Block2),(*(((intptr_t))*)&((Block2)))=(intptr_t)(Block2)^(intptr_t)(Block1),(*(((intptr_t))*)&((Block1)))=(intptr_t)(Block1)^(intptr_t)(Block2));
Before anybody mentions it, I've since realized that I should probably make this a function instead of a macro. Or even better, just use that extra variable to do the swap, it isn't hard.
But I want to know why this macro doesn't work. The brackets seem to match exactly as I wanted them to, so why is it complaining?
The LVALUE_CAST is something I took from #Jens Gustedt's answer in this SO question.
Update:
The macro call that produces that preprocessor output looks like this:
XOR_CAST_SWAP(intptr_t, Block1, Block2);
I don't believe you can wrap types in arbitrary levels of parentheses.* So this compiles fine:
((*(intptr_t*)&((Block1)))=(intptr_t)(Block1)^(intptr_t)(Block2),(*(intptr_t*)&((Block2)))=(intptr_t)(Block2)^(intptr_t)(Block1),(*(intptr_t*)&((Block1)))=(intptr_t)(Block1)^(intptr_t)(Block2));
* Disclaimer: this is purely empirical! I don't intend to peruse the standard to figure out what the details are...
I'm trying to compile some code I found online, but gcc keeps getting me error messages.
Is there any way I can bypass the error, and compile?
ttys000$ gcc -o s-proc s-proc.c
s-proc.c:84:18: error: \x used with no following hex digits
Here's the line it keeps bitching about:
printf("\x%02x", ((unsigned char *)code)[i]);
...
First post on here, so if I broke any rules or wasn't specific enough, let me know.
You can't ignore errors1. You can only ignore warnings. Change the code.
printf("\\x%02x", ((unsigned char *)code)[i]);
It's just a guess, since without documentation or input from the original author of the code, we have no solid evidence for what the code is actually supposed to do. However, the above correction is extremely plausible, it's a simple typo (the original author forgot a \), and it's conceivable that the author uses a C compiler which silently ignores the error (Python has the same behavior by design).
The line of code above, or something almost exactly like it, is found in probably tens of thousands of source files across the globe. It is used for encoding a binary blob using escape sequences so it can be embedded as a literal in a C program. Similar code appears in JSON, XML, and HTML emitters. I've probably written it a hundred times.
Alternatively, if the code were supposed to print out the character, this would not work:
printf("\x%02x", ((unsigned char *)code)[i]);
This doesn't work because escape sequences (the things that start with \, like \x42) are handled by the C compiler, but format strings (the things that start with %, like %02x) are handled by printf. The above line of code might only work if the order were reversed: if printf ran first, before you compiled the program. So no, it doesn't work.
If the author had intended to write literal characters, the following is more plausible:
printf("%c", ((unsigned char *)code)[i]); // clumsy
putchar((unsigned char *)code)[i]); // simpler
So you know either the original author simply typo'd and forgot a single \ (I make that mistake all the time), or the author has no clue.
Notes:
1: An error means that GCC doesn't know what the code is supposed to do, so continuing would be impossible.
Looks like you want to add a prefix of x to the hex number. If yes, you can drop the \:
printf("x%02x", ((unsigned char *)code)[i]);
The reason you are getting error is \x marks the beginning of a hex escape sequence.
Example: printf("\x43\x4f\x4f\x4c");
Prints
COOL
As C has an ASCII value of 0x43.
But in your case the \x is not followed by hex digits which causes parse errors. You can see the C syntax here it clearly says:
hex-escape ::= \x hex-digit ∗
Escape the \ with another \
printf("\\x%02x", ((unsigned char *)code)[i]);
By the way, you can't force GCC to continue compilation after an error, as as error is an error because it prevents further logical analysis of the source code which is impossible to resolve.
Could someone please help and tell me how to include IEEE mathematical functions in MSVC++6? I tried both and , but I still get these errors:
error C2065: 'ilogbf' : undeclared identifier
error C2065: 'scalbnf' : undeclared identifier
Edit 3: Hopefully this will be my final edit. I have come to realize that I haven't properly addressed this question at all. I am going to leave my answer in place as a cautionary tale, and because it may have some educational value. But I understand why I have zero upvotes, and in fact I am going to upvote Andy Ross' answer because I think his is much more relevant (although incomplete at least at the time of writing). It seems to me my mistake was to take the Man definitions I found for ilogbf() a little superficially. It's a function that takes the integer part of the log of a float, how hard can that be to implement ? It turns out what the function is really about is IEEE floating point representation, in particular the exponent (as opposed to the mantissa) part of that representation. I should definitely have realized that before attempting to answer the question! An interesting point to me is how a function can possibly find the exponent part of a float, as I thought a fundamental rule of C is that floats are promoted to doubles as part of a function call. But that's a whole separate discussion of course.
--- End of edit 3, start of cautionary tale ---
A little googling suggests these are defined in some flavors of Unix, but maybe are not in any Posix or ANSI standard and so not provided with the MSVC libraries. If the functions aren't in the library they won't be declared in math.h. Obviously if the compiler can't see declarations for these external symbols it won't be happy and you'll get errors like the ones you list.
The obvious work around is to create your own versions of these functions, using math functions that are provided. eg
#include <math.h>
int ilogbf( float f )
{
double d1 = (double)f;
double d2 = log(d1);
int ret = (int)d2;
return ret;
}
Edit: This isn't quite right. Apparently, this function should use log to the base 2, rather than natural logs, so that the returned value is actually a binary exponent. It should also take the absolute value of its parameter, so that it will work for negative numbers as well. I will work up an improved version, if you ask me in a comment, otherwise I'm tempted to leave that as an exercise for the reader :-)
The essence of my answer, i.e. that ANSI C doesn't require this function and that MSVC doesn't include it, is apparently correct.
Edit 2: Okay I've weakened and provided an improved version without being asked. Here it is;
#include <math.h>
int ilogbf( float f )
{
double d1 = (double)f;
if( d1 < 0 )
d1 = -d1;
double d2 = log(d1) / log(2); // log2(x) = ln(x)/ln(2)
int ret = (int)d2;
return ret;
}
These are C99 functions, not IEEE754-1985. Microsoft seems to have decided that their market doesn't care about C99 support, so they haven't bothered to provide them. This is a shame, but unless more of you (developers) complain, there's no reason to expect that the situation will change.
The brand new 754 standard, IEEE754-2008, requires these functions (Clause 5.3.3, "logBFormat operations"), but that version of the standard won't be widely adopted for several more years; even if it does reach wide adoption, Microsoft hasn't seen fit to provide these functions for the ten years they've been in C99 so why would they bother to provide them just because they're in the IEEE754 standard?
edit: note that scalb and logb are defined in the IEEE754-1985 Appendix "Recommended Functions and Predicates", but said appendix is explicitly "not a part of" said standard.
If you know you're on an IEEE system (and these days, you do), these functions aren't needed: just inspect the bits directly by unioning the double with a uint64_t. Presumably you're using these functions in the interest of efficiency in the first place (otherwise you'd be using more natural operations like log() or exp()), so spending a little effort on matching your code to the floating point representation is probably worthwhile.