Impossible multi-dimensional array in C - c

I was reading some introductory material on programming in C.
The following example was presented:
int matrix[][] = {{ 1,2,3}, {5,6,7}};
As gcc (7.5.0 in my case) and clang (6.0.0 in my case) did not compile, I tried several C standards (c89, c90), but none worked.
Is there a C standard version in which this is valid?

It is not legal in C. The error message is self-explanatory:
declaration of 'matrix' as multidimensional array must have bounds for
all dimensions except the first
you need to provide all the sizes except the first:
int matrix[][3] = {{ 1,2,3}, {5,6,7}};
int matrix[][2][3] = {{{ 1,2,3}, {5,6,7}}, {{ 1,2,3}, {5,6,7}}};
/* etc etc*/
Is there a C standard version in which this is valid?
NO

Let's take a look at your syntax :
int matrix[][] = {{ 1,2,3}, {5,6,7}};
here, in C language you need to declare the size of all the dimensions except the first one(which is optional), and here you didn't declared the second dimension, so obviously it will give you a syntax error as it is not valid in C.
If we take a variable x, then in a generalized form we can say that the correct syntax is :
int matrix[][x] = {{1,2,3,...., x terms}, {1,2,3,....,x terms},.... upto your desired no. of terms};
and for your array :
int matrix[][3] = {{1,2,3},{5,6,7}};
Some examples for your reference are given below :
int matrix[] = {1,2,3};
int matrix[][4] = {{1,2,3},{4,5,6,7}};
int matrix[][4][5] = {{1,2},{3,4,5,6},{7,8,9,10,11}};
int matrix[][5][3] = {{1,2,3,4,5,6},{7,8,9,10,11},{12,13,14}};
Now, let's come to your last question:
Is there any version of standard C which allows to do so?
Answer is: No! there is no such version of C currently available which allows us to do so. It is a strict syntax convention that you should follow.
I hope so this explanation was helpful!

C was designed to allow for the possibility of single-pass processing. Given a declaration like:
int foo[][4] = {{1,2,3},{4,5,6,7}};
a compiler could start placing things in memory as it read them. When it finds the first close brace, it would know that it needs to insert space before the 4 because it would know that it had output 3 values but the inner dimension was 4. Had the construct instead been:
int foo[][] = {{1,2,3},{4,5,6,7}};
the compiler would have no way of knowing that space would be needed after the 3 until after it had read the 7, by which point it would have already written the values 1 through 6 into consecutive storage locations. While it's possible that some implementations could conceivably use multi-pass scanning so they could extend the language to accommodate such constructs, I would not expect any compiler vendor to expect the benefits to justify the cost.

Related

Declare multiple integer variables in C

Before i start, I am not good at English so I use a translator, so you may not understand well.
I'm so sorry. But the content of the question is easy, so there is probably no difficulty understanding.
One day I don't remember very well, but I saw a code similar to the one below.
#include <stdio.h>
int main(){
int a,b,c = 1,d,e;
return 0;
}
At that time, I just let it go. But now that I think about it, I'm curious.
So I checked the value of C, and it was printed 1.
And I changed 1 to 0 and confirmed that the value of C was zero.
This result was the same for the other numbers.
I've never seen a code like this before.
In the meantime, I knew that to declare a number of variables, I would have to do as the code below.
int a = 1, b = 2, c = 3;
But it wasn't what I knew.
After several experiments, I found that a,b,c,d,e were independent variables.
Except for C, a,b,d,e contained garbage value.
I wonder why this is grammatically possible and why the values are not allocated in order from left to right.
Once again, I'm sorry for using the translator.
int a,b,c = 1,d,e;
is the same as
int a;
int b;
int c = 1;
int d;
int e;
Except for C, a,b,d,e contained garbage value - This is because only C is both declared and initialized with the value 1. Others are just declared in a random memory location, hence has garbage values
I wonder why this is grammatically possible - It is a right syntax still. See the answer by #pmg
In the meantime, I knew that to declare a number of variables, I would have to do as the code below. int a = 1, b = 2, c = 3; - Here you are actually declaring as well as initializing them with different values. You can always declare any number of variables (of the same datatype) in a single statement.

Cannot figure out how to format strings in an array (C) – very new to comp sci

I've looked through many questions here, but the syntax is unfamiliar to me. I am trying to write a program in C, that given a composer's name, will give you the instrumentation that composer used in orchestral music. I am trying to figure out how to format strings in an array, but the compiler won't recognize them. I have tried using one variable, no luck. Right now, only errors from compiler are "undeclared identifiers" for each indexed composer's name in j[0], j[1], j[2]. So far I have:
#include <stdio.h>
#include <cs50.h>
int main(void)
{
printf("Henlo, (')> I will determine your average orchestral instrumentation per composer.\n");
printf("Your options are: JS_Bach, Mozart, Beethoven, Brahms, Wagner, R_Strauss, Ravel, and Debussy.\n");
string i = get_string("Composer: "); //get_string (from <cs50.h> prompts the user to enter text
string j[8];
j[0] = JS_Bach; //undeclared identifiers for j[0] thru j[7]
j[1] = Mozart;
j[2] = Beethoven;
j[3] = Brahms;
j[4] = Wagner;
j[5] = R_Strauss;
j[7] = Ravel;
j[7] = Debussy;
if (i == j[0])
{
printf("2fl, 2-3ob, maybe d'amore/da caccia, 3trp, timp, vln.I, vln.II, vla, SATB choir + solo, bc\n");
}
else if (i == j[1])
{
printf("1-2fl, 2ob, maybe 2cl/basset 2bsn, 2hrn, 2trp, timp, vln.I, vln.II, vla, vlc, cb\n");
//same format with different text in printf for j[2] thru j[7], (won't waste space here with the rest)
I have also seen questions with code using char** and things like that; could someone explain the asterisk's purpose? Do I need to declare items as char instead of string? The type string is defined by <cs50.h>. Not sure if I will need another function library to use strings in arrays?
You are referring to the names as identifiers and not as constants like you want them to be. Change Wagner to "Wagner" for example. You get an error because these identifiers were never defined before being used by you.
Also, right now when you are comparing the strings you are comparing their addresses in memory. Consider using strcmp if you want to compare the strings and not their addresses.

Difference between declaration terminated incorrectly and declaration syntax error in C

I want to know when this difference happen Declaration terminated error and declaration syntax.
my code for Declaration terminated error:
int a=12,245;
and code for declaration syntax error:
int a=10 20 30;
You can say
int a = 12245;
and you're initializing a to the integer 12245.
You can say
double a = 12.245;
and you're initializing a to the floating-point decimal number 12.245.
If you want to confuse people, you might be able to say
int a = (12,245);
and this is like saying "I want to initialize a to 12, no, I mean 245". (a would end up holding 245).
But you can't say
int a = 12,245;
The comma character can be used in several different ways in C, but there are also several ways that it can not be used.
In C source code, you have to use the full stop . as a decimal point, and you can't use a comma to group numbers into thousands or lakh or anything.
What you can use commas for are to separate the arguments in a function call, or to declare several variables at once, or as the comma operator. But these are all quite different, and int a = 12,245; doesn't end up fitting any of them.
For completeness, here are argument-separating commas in a function call:
printf("%d %c %s %f\n", 1, '2', "three", 4.5);
Here are commas separating multiple declarations:
int a = 12, b = 245;
Here are comma operators:
for(i = 0, j = n; i < j; i++, j--)
Integer can not tape floating point values like 10,3, Integer can only store natural numbers like 180! If you want to use floating point values, use float or double
In C, there is no difference. Both programs fail to conform to the syntax of the language.
C does not specify the text of error or warning messages produced by a compiler. Most compilers make some effort to produce error messages which help the programmer understand what the error is. Some do better than others, but none is perfect.
Whatever compiler you are using, in its current version, happens to produce two different error messages for that code. How it decided which message to produce is something probably only the authors of that compiler could tell you. If you feel that one or the other error message is significantly misleading, you could file a bug report or a formal complaint, if the compiler you are using has some sort of user-support channel which allows you to do one of those things.

passing a constant through a function in C

I have some C function which, among other things, does a modulo operation. So it looks something like
const int M = 641;
void func( ...parameters..) {
int x;
... some operations ...
x %= M;
... some more operations ...
}
Now, what is crucial for me is that the number M here is a constant. If I would not tell the compiler that M is a constant, then I would get much slower performance.
Currently, I am very happy with my function func( .. ) , and I want would like to extend it, so it can work on different moduli. But again, it is crucial here that these moduli are fixed. So I would like to be able to do something like
const int arrayM[] = {641, 31, 75, 81, 123};
and then have for each index in the array of constants array_M[i] a version of the function func, say func_i, which is a copy of the function func, but where array_M[i] replaces the role of M.
In practice, my array of constants arrayM[] will consist of around 600 explicit prime numbers, which I will choose in a particular way so that x % array_M[i] compiles to a very fast modulus function (for instance Mersenne primes).
My question is: How do I do this in C without making 600 copies of my function func, and changing the variable M in the code each time ?
Finally, I would like to ask the same question again for CUDA code. So if I would have a cuda-kernel, where at some point in the code a modulus M operation is carried out, and I want to have different copies of the same kernel (one for each index of array_M).
You may use a define like:
#define F(i,n) void func_##i() { printf("%d\n",n); }
#include <stdio.h>
F(1,641)
F(2,31)
...
int main() {
func_1();
func_2();
}
It is possible to obtain the same effect from a list of constant but it is much much more tricky. See recursive macro.
Most compilers will do constant propagation. You need to turn up the optimisation level high. The only way to be sure however is to examine the assembly code, or to explicitly write the code out with the constants folded in, which is ugly and hard to maintain. C++ allows you to specify a scalar as a template.

Why Right Associativity doesn't work with the declaration statement

int a=b=c=10; //invalid statement
But following are valid statements
int a,b,c;
a=b=c=10;
First one is invalid as b assigned to a even before b got its value.
But the second case is valid as equal(=) sign is having right associative i.e
"=" sign will start getting preference from the right side.
My question is: why doesn't Right Associativity apply in the first case?
Does it mean that Associativity doesn't work with the declaration statement?
I need more clarity on this.
It doesn't work because it isn't syntactically correct. As you show in the second example, more than one variable of a type are declared using commas as a separator. If instead b and c are already declared then things work fine. For example this works:
int b,c;
int a=b=c=10;
You can even do this (at least with VS2010 compiler):
int b,c,a=b=c=10;
Mind you I'd say that looks BAD, and advise against it.
If it'd be not just an exercise but you had tested this with a real compiler, you probably would have given us a bit more information of actually what displeases the compiler.
Part of the answer would be to notice the two different roles of the = operator. One is assignment and one is initialization. Your example
int a = b = c = 10;
is equivalent to
int a = (b = (c = 10));
So the two = on the right are assignments and not initializations. And in an assignment the left hand side must be well defined.
Variables need to be declared first and then assigned a value or used in expressions.

Resources