Using c macro for variables - c

I want to access several variables of the form:
int arr1=1;
int arr2=1;
int arr3=1;
So I wrote
#define arr(i) arr##i
but following code piece doesnt work as i expect
#include <stdio.h>
int main(){
int arr1=1;
int arr2=1;
int arr3=1;
int j;
for(j=1; j<3; j++)
printf("%d",arr(j));
return 0;
}

You cannot do this. Variable names don't exist at runtime in C.
Your macro will expand to arrj, which is an undefined variable name. Use a proper array:
int arr[] = { 1, 1, 1 };
then print arr[j], but loop like this:
for(j = 0; j < sizeof arr / sizeof *arr; ++j)
printf("%d\n, arr[j]);

The macro code is used for pre-processor phase and not for the runtime phase
if you generate your preprocessor code with gcc -E. You will see that your code is equivalent to:
int main(){
int arr1=1;
int arr2=1;
int arr3=1;
int j;
for(j=1; j<3; j++)
printf("%d",arrj);
return 0;
}
When you build your program, the gcc generate anoter c code from your c code and in which it replace all macros in your code by the macro contents( This phase is called preprocesser phase). and then generate asm code and then generate the binary file.
You can see the generated c code (from your code) by the gcc -E: code of preprocessor phase

So that's going to produce arrj as a result.
The macro phase of C is something that happens before the program is run, even before it is parsed as actual C.
Long ago, the preprocessor was a totally separate program that knew very little about the C language.
Like most compilers today, cc back then just ran the different phases. Before it ran the compiler, assembler, and linker, it ran cpp, the C preprocessor.
And cpp just parsed the definitions, then it expanded the macros, and then it quit. Then cc would run the compiler. These days, the macro expansion is built in to the compiler proper but it processes the textual input of the program according to the original design.
There is still a /usr/bin/cpp on some systems today, but it's usually just a shell script that runs the compiler image with options that say don't compile.

Related

Preprocessor constant folding

I have a fundamental question regarding the C preprocessor constant evaluation and I would like some help in understanding if the preprocessor helps in optimizing the code in a situation like this. I understand that the preprocessor merely "replaces text" in the code. By that rule, even constant expressions get replaced in the code. For instance, the below code:
#include <stdio.h>
#define MY_NUM 2+2*2
int main()
{
int a = 6/MY_NUM;
printf("a: %d\n", a);
return 0;
}
The value of a comes to 7. This is because the preprocessed code looks something like this:
int main()
{
int a = 6/2+2*2;
printf("a: %d\n", a);
return 0;
}
I can see that MY_NUM did not evaluate to 6 before the compilation kicks in. Of course the compiler then optimizes the code by evaluating the value of a at compile time.
I am not sure if preprocessor constant folding happens or not or if it is even possible. Or is there any way (flag in gcc) to enable it. The regular -O optimizations do not enable this. Is there anyway we could change the behavior of the preprocessor here?
I am using gcc 4.8.4 for my code.
No, the only time the preprocessor evaluates any expression is in #if / #elif.
You can fake arithmetic by implementing it in terms of token concatenation and a ton of macros, but that's much harder than simply doing
#define MY_NUM (2+2*2)
But there's no simple compiler switch because macro expansion is just token replacement.

C - Invalid syntax allowed by compiler?

When I learned C using Microsoft Visual Studio, it didn't allow me to create an array with a non-constant size. I had to either put a value like int arr[5]; or do #define size 5 and do int arr[size];. However today using Clion, I noticed it allows me to do the following:
#include <stdio.h>
int main()
{
printf("Enter a value: ");
int x;
scanf("%d", &x);
int arr2[x];
for (int i = 0; i < x; i++)
{
arr2[i] = i;
printf("Array at %d is %d.\n", i, arr2[i]);
}
return 0;
}
This C code compiles and runs without any problems -- no segment fault or anything. What's going on? Is this legal C code and I just learned in an IDE that didn't allow it, or is this invalid C code and I'm just using a bad compiler? On my other computer which is using Linux, I even installed GCC 7.2 and the same syntax is allowed. I don't understand. Is this a CLion issue, CMake issue, or a C lang issue?
My compiler and CMake are listed below. Thanks.
This is valid C. It is referred to as a variable length array (VLA). This feature was added to the language as part of the C99 standard.
MSVC is well known for not supporting many C99 and later features, including VLAs.

expression did not evaluate to a constant ERROR code

So I am trying to learn C and I am trying to make this code so it will sort of the array's elements from lowest to highest, it's obviously not complete but I just wanted to see the random numbers printed.
Anyway, I am getting an error E0028 & C2131 (Visual Studios) that says "expression must have a constant value" & "expression did not evaluate to a constant." The int goals[howMany];is where VS is telling me I have an error
int main()
{
int i, temp, swapped;
int howMany = 10;
int goals[howMany];
for (i = 0; i < howMany; i++) {
goals[i] = (rand() % 25) + 1;
}
printf("Original List\n");
for (i = 0; i < howMany; i++) {
printf("%d \n", goals[i]);
}
return 0;
}
This is exactly how the code is written out in the tutorial I am watching and they are using Code:Blocks. I know sometimes those two compilers can be different but I was hoping someone can let me know what's going on or how to fix this.
Visual studio doesn't support variable length arrays. C is a little tricky, and the compiler/flags you use matters. For example, if you were to compile with the gcc compiler, using the -std=c99 flag would allow you to run your code with no errors (since -std=c99 supports variable length arrays).
I'm not sure exactly how compilation in Visual Studio works, but that's your problem. I usually don't like C programming in VS for this reason. It's much easier for me to use something like Vim, and compile at the command like so that I can specify compiler settings.
In order to use rand(), you need to include the according lib and then "plant a rand seed" : take a look at C Rand Function
const howMany = 10;
This most likely is just the compiler you are using. I suppose it's a safe guard to prevent a segmentation fault. If howMany variable is changed after being used to initialize the array then a seg fault will will definitely result.A seg fault is when you access something out of bounds. If you try to change a const variable then the compiler will not let you.By making howMany const this will prevent any such errors.

Matrix not zero-filled on declaration

I was trying to debug my code in another function when I stumbled upon this "weird" behaviour.
#include <stdio.h>
#define MAX 20
int main(void) {
int matrix[MAX][MAX] = {{0}};
return 0;
}
If I set a breakpoint on the return 0; line and I look at the local variables with Code::Blocks the matrix is not entirely filled with zeros.
The first row is, but the rest of the array contains just random junk.
I know I can do a double for loop to initialize manually everything to zero, but wasn't the C standard supposed to fill this matrix to zero with the {{0}} initializer?
Maybe because it's been a long day and I'm tired, but I could've sworn I knew this.
I've tried to compile with the different standards (with the Code::Blocks bundled gcc compiler): -std=c89, -std=c99, std=c11 but it's the same.
Any ideas of what's wrong? Could you explain it to me?
EDIT:
I'm specifically asking about the {{0}} initializer.
I've always thought it would fill all columns and all rows to zero.
EDIT 2:
I'm bothered specifically with Code::Blocks and its bundled GCC. Other comments say the code works on different platforms. But why wouldn't it work for me? :/
Thanks.
I've figured it out.
Even without any optimization flag on the compiler, the debugger information was just wrong..
So I printed out the values with two for loops and it was initialized correctly, even if the debugger said otherwise (weird).
Thanks however for the comments
Your code should initialize it to zero. In fact, you can just do int matrix[MAX][MAX] = {};, and it will be initialized to 0. However, int matrix[MAX][MAX] = {{1}}; will only set matrix[0][0] to 1, and everything else to 0.
I suspect what you are observing with Code::Blocks is that the debugger (gdb?) is not quite showing you exactly where it is breaking in the code - either that or some other side-effect from the optimizer. To test that theory, add the following loop immediately after the initialization:
``` int i,j;
for (i = 0; i < MAX; i++)
for (j = 0; j < MAX; j++)
printf("matrix[%d][%d] = %d\n", i, j, matrix[i][j]);
```
and see if what it prints is consistent with the output of the debugger.
I am going to guess that what might be happening is that since you are not using matrix the optimizer might have decided to not initialize it. To verify, disassemble your main (disass main in gdb and see if the matrix is actually being initialized.

how to elegantly construct long argument lists that iterate through arrays in C

I have a C function that takes variable arguments, and I need to call it with a very long list of arguments, where the arguments all step through the elements of an array. Example:
myFunction( A[0], B[0], A[1], B[1], A[2], B[2], A[3], B[3], ..... A[N], B[N] );
where N is typically 100-200.
I would prefer not having to construct this call manually every time I make N bigger, and got to thinking, is there an elegant way to do this?
I tried something like:
i=0;
myFunction( A[i], B[i++], A[i], B[i++], A[i], B[i++], A[i], B[i++], ..... A[i], B[++] );
but of course that fails. What is preferred about it, however, is anytime I make N larger, I can simply copy the same line over and over, instead of having to ensure each array index is correct, which is quite tedious.
Changing myFunction() is not an option.
I wish C had a way to construct function calls on the fly, like:
for( i = 0 ; i <= N ; i++ )
{
CONSTRUCT_CALL( myFunction, A[i], B[i] );
}
which would be exactly what I want, but of course that's not an option.
Is there anything that might be easier or more elegant?
Thank you very much.
There is no standard C way of doing that (synthesizing a variadic call at runtime). But...
you can use libffi which is designed to handle such issues (so I recommend it)
you could consider GCC specific Builtins for Constructing Calls
you could have some fixed limit on the arity (e.g. 500) and have some C file generated with some (shell, awk, Python, ...) script doing a switch on the 500 cases, one for each arity.
you might consider generating some C code at runtime into _gen123.c, compile it into a dynamically loadable plugin (e.g. forking some gcc -shared -fPIC -Wall -O _gen123.c -o _gen123.so command on Linux), then loading that plugin (with dlopen(3) on Linux or Posix)
you might consider some just-in-time compilation library (e.g. libjit, llvm, GNU lightning, asmjit, ...)
Of course, avoid several i++ in a single call. Avoid undefined behavior, since bad things could happen.
There is something very bad in your design.
Rewrite your myFunction so it takes two arrays (A and B) and then takes numer of indices to use.
A short example of calling such a function:
int A[100];
int B[100];
int c = myFunction(A, B, 100);
A possible implementation of myFunction:
int myFunction(int* A, int* B, int count)
{
int result = 0;
for(int j = 0; j < i; j++)
result += A[j] + B[j]*2;
return result;
}

Resources