C symbolic constant + strcture - c

Given the following snippet of code:
#include <stdio.h>
#include <stdlib.h>
#define MAX_SIZE 15
typedef struct{
int touchdowns;
int interceptions;
int tackles[MAX_SIZE + 1]; //this is the line in question
}stats;
The question posed to me was, "Why does this line [denoted above] add 1 to the possible number of tackles?"
----NOT why would one want too, but how/why does it work. Why is it valid code in otherwords, not necessarily valid logic. -Clarification
I'm unsure of how to answer this question in detail. Any help would be appreciated.

As Armin pointed out, the token MAX_SIZE is replaced by the preprocessor. But for clarification, that's not why it works/compiles in the end. The actual requirement for this to compile is, that the array size is a constant integral expression, which applies to the code in question.

MAX_SIZE is replaced by 100 when code is compiled and the line becomes
int tackles[100 + 1];
which is the same as
int tackles[101];
From documentation:
To define preprocessor macros we can use #define. Its format is:
#define identifier replacement
When the preprocessor encounters this directive, it replaces any occurrence of identifier in the rest of the code by replacement. This replacement can be an expression, a statement, a block or simply anything. The preprocessor does not understand C++, it simply replaces any occurrence of identifier by replacement.
#define TABLE_SIZE 100
int table1[TABLE_SIZE];
int table2[TABLE_SIZE];
After the preprocessor has replaced TABLE_SIZE, the code becomes equivalent to:
int table1[100];
int table2[100];

Probably because tackles is an array terminated by a terminator value (such as -1), similar how C strings are terminated by the null character. Note how the structure has no member denoting the number of tackles.

Related

Can a macro remove characters from its arguments?

Is it possible to define a macro that will trim off a portion of the string argument passed in?
For example:
//can this be defined?
#define MACRO(o) ???
int main(){
printf(MACRO(ObjectT)); //prints "Object" not "ObjectT"
}
Would it be possible for a macro that trim off the last character 'T'?
You can do it for specific strings that you know in advance, presented to the macro as symbols rather than as string literals, but not for general symbols and not for string literals at all. For example:
#include <stdio.h>
#define STRINGIFY(s) # s
#define EXPAND_TO_STRING(x) STRINGIFY(x)
#define TRUNCATE_ObjectT Object
#define TRUNCATE_MrT Pity da fool
#define TRUNCATE(s) EXPAND_TO_STRING(TRUNCATE_ ## s)
int main(){
printf(TRUNCATE(ObjectT)); // prints "Object"
printf(TRUNCATE(MrT)); // prints "Pity da fool"
}
That relies on the token-pasting operator, ##, to construct the name of a macro that expands to the truncated text (or, really, the replacement text), and the stringification operator, #, to convert the expanded result to a string literal. There's a little bit of required macro indirection in there, too, to ensure that all the needed expansions are performed.
Well, at least it should print "Object"...
//can this be defined?
#define MACRO(o) #o "\b \b"
int main(){
printf(MACRO(ObjectT)); //prints "Object" not "ObjectT"
}
And no, you can't strip character using preprocessor only without actual C code (say, malloc+strncpy) to do that.
With the preprocessor? No. It sounds like what you really want to do is something like this:
Code not tested
#define STRINGIFY(o) #o
char* serialize(char* s)
{
if (strcmp(s, "ObjectT") == 0) return "Object";
}
int main(){
printf(serialize(STRINGIFY(#o))); //prints "Object" not "ObjectT"
}

Why a comma can be missed in a printf() call?

I am used to C# or Java.
How could the following statement be correct in C?
printf("aaa" "bbb");
On my Xubuntu 15.04 with GCC 4.9. It outputs:
aaabbb
And as I tried, below works too!
CHAR *p = "aaa""bbb""ccc";
printf(p);
It outputs:
aaabbbccc
I think there should be a comma but in that way, the first string will be treated as a format string. So, is this syntax legal?
Yes it is legal syntax because of translation phase 6 in ISO C99, #5.1.1.2 Translation phases:
Adjacent string literal tokens are concatenated.
As mentioned adjacent strings are concatenated by the compiler. But if you want to see some difference you may add a \0 null terminator in your strings.
On adding the aaa\0 your o/p will be just aaa as printf will print till it finds the 1st \0 null terminator.
#include<stdio.h>
int main()
{
printf("aaa\0" "bbb");
}
Output
aaa
The two strings are just concatenated by the compiler.
When the compiler see two consecutive string literals, it concatenate them (at parsing time in the compiler), like you observe. This won't work (compiler syntax error) for non literals.
The comma operator is unrelated to concatenation. It evaluates first the left operand, then the right one, and discards the result of the left, giving the right result. It is useful for side effects (like progn in Lisp, ; in Ocaml, begin in Scheme). Of course, the comma is also used to separate arguments in calls.
As #Jens said, adjacent string literals are concatenated by the compiler.
One reason for this is so that you can do preprocessor things like this:
#include <stdio.h>
#if defined(__linux__)
#define MY_OS "linux"
#elif defined(_WIN32)
#define MY_OS "windows"
#else
#define MY_OS "probably something BSD-derived"
#endif
int main(void){
printf("my os is " MY_OS "\n");
}
Which saves everybody a lot of time.

When is using whitespace for readability NOT allowed?

C seems to be pretty permissive when it comes to whitespace.
We can use or omit whitespace around an operator, between a function name and its parenthesized list of arguments, between an array name and its index, etc. in order to make code more readable. I understand this is a matter of preference.
The only place I can think of where whitespace is NOT allowed is this:
#include < stdio.h > // fatal error: stdio.h : No such file or directory
What are the other contexts in C where whitespace cannot be used for readability?
In most cases, adding whitespace within a single token either makes the program invalid or changes the meaning of the token. An obvious example: "foo" and " foo " are both valid string literals with different values, because a string literal is a single token. Changing 123456 to 123 456 changes it from a single integer constant to two integer constants, resulting in a syntax error.
The exceptions to this involve the preprocessor.
You've already mentioned the #include directive. Note that given:
#include "header.h"
the "header.h" is not syntactically a string literal; it's processed before string literals are meaningful. The syntax is similar, but for example a \t sequence in a header name isn't necessarily replaced by a tab character.
Newlines (which are a form of whitespace) are significant in preprocessor directives; you can't legally write:
#ifdef
FOO
/* ... */
#endif
But whitespace other than newlines is permitted:
# if SPACES_ARE_ALLOWED_HERE
#endif
And there's one case I can think of where whitespace is permitted between preprocessor tokens but it changes the meaning. In the definition of a function-like macro, the ( that introduces the parameter list must immediately follow the macro name. This:
#define TWICE(x) ((x) + (x))
defines TWICE as a function-like macro that takes one argument. But this:
#define NOT_TWICE (x) ((x) + (x))
defines NOT_TWICE as an ordinary macro with no arguments that expands to (x) ((x) + (x)).
This rule applies only to macro definitions; a macro invocation follows the normal rules, so you can write either TWICE(42) or TWICE ( 42 ).
White spaces are not allowed for readability (are significant) within a lexical token. I.e. within an identifier (foo bar is different from foobar), within a number (123 456 is different from 123456), within a string (that's your example basically) or within an operator (+ + is different from ++ and + = is different from +=). Between those you can add as much white space as you want, but when you add white space inside such a token you will break the lexical token into two separate tokens (or change the value in case of string constants), thus changing the meaning of your code .
In most cases the code with the added white space is either equivalent to the original code or results in a syntax error. But there are exceptions. For example:
return a +++ b;
is the same as
return a ++ + b;
but is different from:
return a + ++ b;
As I recall you need to be very careful with function-like macros, as in such dummy example:
#include <stdio.h>
#define sum(x, y) ((x)+(y))
int main(void)
{
printf("%d\n", sum(2, 2));
return 0;
}
the:
#define sum(x, y) ((x)+(y))
is different thing than say:
#define sum (x, y) ((x)+(y))
The latter one is object-like macro, that replaces exactly with (x, y) ((x)+(y)), that is parameters are not being subsituted (as it happens in function-like macro).

Different behavior in visual c++ versus gcc/clang while stringifying parameter which contains comma

I'm using stringizing operator to convert parameter which may contains comma passed to a macro into string. As I know, some characters cannot be stringified – notably, the comma(,) because it is used to delimit parameters and the right parenthesis()) because it marks the end of the parameter. So I use a variadic macro to pass commas to the stringizing operator like this:
#include <stdio.h>
#define TEST 10, 20
#define MAKE_STRING(...) #__VA_ARGS__
#define STRING(x) MAKE_STRING(x)
int main()
{
printf("%s\n", STRING(TEST) );
return 0;
}
it works fine. But it occurs to me what would happen without variadic macro, so I modify the macro: #define MAKE_STRING(x) #x. It compiles fine unexpectedly in visual c++ 2008/2010, and output 10, 20 while gcc/clang give the compilation error as expected:
macro "MAKE_STRING" passed 2 arguments, but takes just 1
So my question: is the Visual c++ doing additional work or the behavior is undefined?
VS in general allows extra parameters in macros and then just drops them silently:
STRING(10, 20, 30) - still works and prints 10. This is not the case here, but it pretty much means VS don't even have the error gcc threw at you.
It's not any additional work but "merely" a difference in substitution order.
I am not sure if this will answer your question but i hope this will help you solving your problem. When defining a string constant in C, you should include it in double quotes (for spaces). Also, the # macro wrap the variable name inside double quotes so, for example, #a become "a".
#include <stdio.h>
#define TEST "hello, world"
#define MAKE_STRING(x) #x
int main()
{
int a;
printf("%s\n", TEST);
printf("%s\n", MAKE_STRING(a));
return 0;
}
I compiled this code using gcc 4.7.1 and the output is:
hello, world
a
I dunno why this has upvotes, or an answer got downvoted (so the poster deleted it) but I don't know what you expect!
#__VA_ARGS__ makes no sense, suppose I have MACRO(a,b,c) do you want "a,b,c" as the string?
http://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html#Variadic-Macros
Read, that became standard behaviour, variable length arguments in macros allow what they do in variable length arguments to functions. The pre-processor operates on text!
The only special case involving # is ##, which deletes a comma before the ## if there are no extra arguments (thus preventing a syntax error)
NOTE:
It is really important you read the MACRO(a,b,c) part and what do you expect, a string "a,b,c"? or "a, b, c" if you want the string "a, b, c" WRITE THE STRING "a, b, c"
Using the # operator is great for stuff like
#define REGISTER_THING(THING) core_of_program.register_thing(THING); printf("%s registered\n",#THING);

Determine #defined string length at compile time

I have a C-program (an Apache module, i.e. the program runs often), which is going to write() a 0-terminated string over a socket, so I need to know its length.
The string is #defined as:
#define POLICY "<?xml version=\"1.0\"?>\n" \
"<!DOCTYPE cross-domain-policy SYSTEM\n" \
"\"http://www.adobe.com/xml/dtds/cross-domain-policy.dtd\">\n" \
"<cross-domain-policy>\n" \
"<allow-access-from domain=\"*\" to-ports=\"8080\"/>\n" \
"</cross-domain-policy>\0"
Is there please a way, better than using strlen(POLICY)+1 at the runtime (and thus calculating the length again and again)?
A preprocessor directive, which would allow setting POLICY_LENGTH already at compile time?
Use sizeof(). e.g. sizeof("blah") will evaluate to 5 at compile-time (5, not 4, because the string literal always includes an implicit null-termination character).
Use 1+strlen(POLICY) and turn on compiler optimizations. GCC will replace strlen(S) with the length of S at compile time if the value from S is known at compile time.
I have a similar problem when using an outdated compiler (VisualDSP) on an embedded platform which does not yet support C++11 (and so I can't use constexpr).
I don't need to evaluate the string length in the precompiler, but I do need to optimize it into a single assignment.
Just in case someone needs this in the future, here's my extremely hacky solution which should work on even crappy compilers as long as they do proper optimization:
#define STRLENS(a,i) !a[i] ? i : // repetitive stuff
#define STRLENPADDED(a) (STRLENS(a,0) STRLENS(a,1) STRLENS(a,2) STRLENS(a,3) STRLENS(a,4) STRLENS(a,5) STRLENS(a,6) STRLENS(a,7) STRLENS(a,8) STRLENS(a,9) -1)
#define STRLEN(a) STRLENPADDED((a "\0\0\0\0\0\0\0\0\0")) // padding required to prevent 'index out of range' issues.
This STRLEN macro will give you the length of the string literal that you provide it, as long as it's less than 10 characters long. In my case this is enough, but in the OPs case the macro may need to be extended (a lot). Since it is highly repetitive you could easily write a script to create a macro that accepts 1000 characters.
PS: This is just a simple offshoot of the problem I was really trying to fix, which is a statically-computed HASH value for a string so I don't need to use any strings in my embedded system. In case anyone is interested (it would have saved me a day of searching and solving), this will do a FNV hash on a small string literal that can be optimized away into a single assignment:
#ifdef _MSC_BUILD
#define HASH_FNV_OFFSET_BASIS 0x811c9dc5ULL
#define HASH_TYPE int
#else // properly define for your own compiler to get rid of overflow warnings
#define HASH_FNV_OFFSET_BASIS 0x811c9dc5UL
#define HASH_TYPE int
#endif
#define HASH_FNV_PRIME 16777619
#define HASH0(a) (a[0] ? ((HASH_TYPE)(HASH_FNV_OFFSET_BASIS * HASH_FNV_PRIME)^(HASH_TYPE)a[0]) : HASH_FNV_OFFSET_BASIS)
#define HASH2(a,i,b) ((b * (a[i] ? HASH_FNV_PRIME : 1))^(HASH_TYPE)(a[i] ? a[i] : 0))
#define HASHPADDED(a) HASH2(a,9,HASH2(a,8,HASH2(a,7,HASH2(a,6,HASH2(a,5,HASH2(a,4,HASH2(a,3,HASH2(a,2,HASH2(a,1,HASH0(a))))))))))
#define HASH(a) HASHPADDED((a "\0\0\0\0\0\0\0\0\0"))
sizeof works at compile time
#define POLICY "<?xml version=\"1.0\"?>\n" \
"<!DOCTYPE cross-domain-policy SYSTEM\n" \
"\"http://www.adobe.com/xml/dtds/cross-domain-policy.dtd\">\n" \
"<cross-domain-policy>\n" \
"<allow-access-from domain=\"*\" to-ports=\"8080\"/>\n" \
"</cross-domain-policy>\0"
char pol[sizeof POLICY];
strcpy(pol, POLICY); /* safe, with an extra char to boot */
If you need a pre-processor symbol with the size, just count the characters and write the symbol yourself :-)
#define POLICY_LENGTH 78 /* just made that number up! */
Per other answers, sizeof(STRING) gives the length (including the \0 terminator) for string literals. However, it has one downside: if you accidentally pass it a char* pointer expression instead of a string literal, it will return an incorrect value–the pointer size, which will be 4 for 32-bit programs and 8 for 64-bit–as the following program demonstrates:
#include <stdio.h>
#define foo "foo: we will give the right answer for this string"
char bar[] = "bar: and give the right answer for this string too";
char *baz = "baz: but for this string our answer is quite wrong";
#define PRINT_LENGTH(s) printf("LENGTH(%s)=%zu\n", (s), sizeof(s))
int main(int argc, char **argv) {
PRINT_LENGTH(foo);
PRINT_LENGTH(bar);
PRINT_LENGTH(baz);
return 0;
}
However, if you are using C11 or later, you can use _Generic to write a macro which will refuse to compile if passed something other than a char[] array:
#include <stdio.h>
#define SIZEOF_CHAR_ARRAY(s) (_Generic(&(s), char(*)[sizeof(s)]: sizeof(s)))
#define foo "foo: we will give the right answer for this string"
char bar[] = "bar: and give the right answer for this string too";
char *baz = "baz: but for this string our answer is quite wrong";
#define PRINT_LENGTH(s) printf("LENGTH(%s)=%zu\n", (s), SIZEOF_CHAR_ARRAY(s))
int main(int argc, char **argv) {
PRINT_LENGTH(foo);
PRINT_LENGTH(bar);
// Will fail to compile if you uncomment incorrect next line:
// PRINT_LENGTH(baz);
return 0;
}
Note this doesn't only work for string literals – it also works correctly for mutable arrays, provided they are actual char[] arrays of fixed length as a string literal is.
As written, the above SIZEOF_CHAR_ARRAY macro will fail for const expressions (although you'd think string literals ought to be const, for backward compatibility reasons they are not):
const char quux[] = "quux is const";
// Next line will fail to compile:
PRINT_LENGTH(quux);
However, we can improve our SIZEOF_CHAR_ARRAY macro so the above example will also work:
#define SIZEOF_CHAR_ARRAY(s) (_Generic(&(s), \
char(*)[sizeof(s)]: sizeof(s), \
const char(*)[sizeof(s)]: sizeof(s) \
))

Resources