Declare multiple integer variables in C - 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.

Related

Impossible multi-dimensional array in 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.

Searching for all integers that occure twice in a vector

I got the task in university to realize an input of a maximum of 10 integers, which shall be stored in a one dimensional vector. Afterwards, every integer of the vector needs to be displayed on the display (via printf).
However, I don't know how to check the vector for each number. I thought something along the lines of letting the pointer of the vector run from 0 to 9 and comparing the value of each element with all elements again, but I am sure there is a much smarter way. I don't in any case know how to code this idea since I am new to C.
Here is what I have tried:
#include <stdio.h>
int main(void)
{
int vector[10];
int a;
int b;
int c;
a = 0;
b = 0;
c = 0;
printf("Please input 10 integers.\n\n");
while (a <= 10);
{
for (scanf_s("%lf", &vektor[a]) == 0)
{
printf("This is not an integer. Please try again.\n");
fflush(stdin);
}
a++;
}
for (b <= 10);
{
if (vector[b] != vector[c]);
{
printf("&d", vector[b]);
c++;
}
b++;
}
return 0;
}
Your code has several problems, some syntactic and some semantic. Your compiler will help with many of the former kind, such as
misspelling of variable name vector in one place (though perhaps this was a missed after-the-fact edit), and
incorrect syntax for a for loop
Some compilers will notice that your scanf format is mismatched with the corresponding argument. Also, you might even get a warning that clues you in to the semicolons that are erroneously placed between your loop headers and their intended bodies. I don't know any compiler that would warn you that bad input will cause your input loop to spin indefinitely, however.
But I guess the most significant issue is that the details of your approach to printing only non-duplicate elements simply will not serve. For this purpose, I recommend figuring out how to describe in words how the computer (or a person) should solve the problem before trying to write C code to implement it. These are really two different exercises, especially for someone whose familiarity with C is limited. You can reason about the prose description without being bogged down and distracted by C syntax.
For example, here are some words that might suit:
Consider each element, E, of the array in turn, from first to last.
Check all the elements preceding E in the array for one that contains the same value.
If none of the elements before E contains the same value as E then E contains the first appearance of its value, so print it. Otherwise, E's value was already printed when some previous element was processed, so do not print it again.
Consider the next E, if any (go back to step 1).

code order with variable length array

In C99, is there a big different between these two?:
int main() {
int n , m;
scanf("%d %d", &n, &m);
int X[n][m];
X[n-1][m-1] = 5;
printf("%d", X[n-1][m-1]);
}
and:
int main(int argc, char *argv[]) {
int n , m;
int X[n][m];
scanf("%d %d", &n, &m);
X[n-1][m-1] = 5;
printf("%d", X[n-1][m-1]);
}
The first one seems to always work, whereas the second one appears to work for most inputs, but gives a segfault for the inputs 5 5 and 6 6 and returns a different value than 5 for the input 9 9. So do you need to make sure to get the values before declaring them with variable length arrays or is there something else going on here?
When the second one works, it's pure chance. The fact that it ever works proves that, thankfully, compilers can't yet make demons fly out of your nose.
Declaring a variable doesn't necessarily initialize it. int n, m; leaves both n and m with undefined values in this case, and attempting to access those values is undefined behavior. If the raw binary data in the memory those point to happen to be interpreted into a value larger than the values entered for n and m -- which is very, very far from guaranteed -- then your code will work; if not, it won't. Your compiler could also have made this segfault, or made it melt your CPU; it's undefined behavior, so anything can happen.
For example, let's say that the area of memory that the compiler dedicates to n happened to contain the number 10589231, and m got 14. If you then entered an n of 12 and an m of 6, you're golden -- the array happens to be big enough. On the other hand, if n got 4 and m got 2, then your code will look past the end of the array, and you'll get undefined behavior -- which might not even break, since it's entirely possible that the bits stored in four-byte segments after the end of the array are both accessible to your program and valid integers according to your compiler/the C standard. In addition, it's possible for n and m to end up with negative values, which leads to... weird stuff. Probably.
Of course, this is all fluff and speculation depending on the compiler, OS, time of day, and phase of the moon,1 and you can't rely on any numbers happening to be initialized to the right ones.
With the first one, on the other hand, you're assigning the values through scanf, so (assuming it doesn't error) (and the entered numbers aren't negative) (or zero) you're going to have valid indices, because the array is guaranteed to be big enough because the variables are initialized properly.
Just to be clear, even though variables are required to be zero-initialized under some circumstances doesn't mean you should rely on that behavior. You should always explicitly give variables a default value, or initialize them as soon as possible after their declaration (in the case of using something like scanf). This makes your code clearer, and prevents people from wondering if you're relying on this type of UB.
1: Source: Ryan Bemrose, in chat
int X[n][m]; means to declare an array whose dimensions are the values that n and m currently have. C code doesn't look into the future; statements and declarations are executed in the order they are encountered.
In your second code you did not give n or m values, so this is undefined behaviour which means that anything may happen.
Here is another example of sequential execution:
int x = 5;
printf("%d\n", x);
x = 7;
This will print 5, not 7.
The second one should produce bugs because n and m are initialized with pretty much random values if they're local variables. If they're global, they'll be with value 0.

Unused Variable Error

I am new to programming and I am currently learning the C language. This is my code. I have tried different fixes, such as making sure I have my semicolons. However, when I go to check my code in the online compiler, I always get unused variable and data definition has no type or storage class. Any information would help me, I assure you, so please let me know what you think a possible solution could be.
//C code
//This program will calculate the average speed of passing cars using a WHILE-END loop
//Developer: Jasmine Tucker
//Date: 7 Sept 2014
#include <stdio.h>
Int main ()
{
/* define variable */
int average_speed;
int car_count;
int car_speed;
};
/* set variable values */
average_speed= 0;
car_count=0;
car_speed=0;
/*WHILE-END loop */
WHILE (car_count > 0)
{
printf (“Enter the car’s speed %s:”, car_count);
scanf (“%d”, & car_speed);
average_speed= car_speed/ car_count
car_count++;
}
printf (“\n The average speed is %d miles per hour. \n”, (average_speed));
return 0;
}
A Few Things:
Int main()
should be
int main()
This is perhaps an easy typo, or the unfortunate side effect of a grammar check.
You could probably do well by studying the standard types in C.
Modifiers aside, there are not very many, and except for special types, _Bool, _Complex, _Imaginary, they are lowercase. (The same holds true for keywords).
Storage class refers to something less commonly used, or at least out of the scope of this program (auto,register,static,extern).
The following definitions use the int type as well, so I will reproduce them here [sic].
/* define variable */
int average_speed;
int car_count;
int car_speed;
};
/* set variable values */
average_speed= 0;
car_count=0;
car_speed=0;
As others have mentioned, there is an extraneous curly brace after the three variables are declared. };
(Notice how sad he looks.)
If you are coming from a language that requires semi-colons after curly braces, you have some hard habits to break.
In any case, commenting that out should remove several errors:
/* }; */
as this is effectively closing the block for main().
As user haini pointed out, you could actually pull the variable definitions outside of main(), allowing them to be accessible to any function. (Use across source files would bring up the aforementioned extern).
Some programmers use special varaible [pre|suf]fixes to distinguish global from local variables.
int g_average_speed;
int g_car_count;
int g_car_speed;
As these variables need to be initialized before use, you can do this in the definition:
int g_average_speed = 0;
int g_car_count = 0;
int g_car_speed = 0;
Often, the use of global variables is discouraged, preferring instead parameter-based sharing of variables, which makes more sense once you introduce multiple functions.
As mentioned, 'WHILE' is not a keyword, while while is. As with the variable types, the list of keywords is very short, and mostly lowercase. It is good to know the keywords so as to avoid using them for variable/function naming.
As far as logic is concerned, your while-loop will never begin, as the expression car_count > 0 will not be satisfied as you've initialised car_count to 0.
While it's easy to hard-code a value, you may probably want to set another variable such as max_cars to an upper limit and check for car_count < max_cars. (Don't forget you're counting from 0).
/* define variable */
int max_cars = 10;
/* rest of variables, init */
while( car_count < max_cars )
Now, aside from the interesting quotations '“' which will give you trouble, and the missing semicolon at average_speed = car_speed / car_count as pointed out again by haini, you should try to step through your loop mentally. Don't ever forget that users are inherently evil and will attempt possibly unforseen values when allowed to interact with the program (scanf()). Negative values and 0 are not out of the question with int and %d, though you may expect some cars to be 'parked' and thus speed 0. Down the line, the unsigned modifier and %u may be of use.
In any case, it's good to get in the habit of sanitizing user input, and/or giving the user an option to opt-out (i.e. "TYPE -1 to break..." ), and checking for invalid or exit codes with an if. (break may be the keyword to pursue in this case)
Your average_speed calculation doesn't quite seem right. Don't forget you're storing values into integers, so you're gonna have some rounding errors.
First think about what happens when your initial case arrives -- what is car_count, and what happens when you divide by that value?
Then, think about the final case, (assuming your upper boundary is 10) in which car_count == 9. You will be assigning car_speed / car_count to average_speed. Is this really what you want?
You can minimize rounding errors and more difficult calculation by maybe 'keeping track' of the total of the speeds, and only one average calculation.
/* define variable */
int total_speed = 0;
In your while loop:
total_speed += car_speed;
or
total_speed = total_speed + car_speed;
And then outside of the loop:
average_speed = total_speed / (car_count - 1);
(The adjustment to car_count is necessary because the value increments after the final loop.)
NOTE: in this limited example, the average_speed variable may not be necessary, unless used outside of the printf().
There are a few issues in your code that I see.
The code will never get in the while loop. If you initialize it to 0, it will never be greater than 0, so will never enter the loop.
Even if it gets into the loop, this is an infinite loop. Keep adding one to a variable would make it so the variable is always greater than 0, so will never exit the loop.
MAJOR ONE: your variables are inside main, but you are using them outside of main!
#include <stdio.h>
Int main ()
{
/* define variable */
int average_speed;
int car_count;
int car_speed;
**};**
(Not sure about this one) but you have an uppercase I in the word int in your method declaration, and uppercase WHILE, should be while.
Code that is not within the main() function causes your errors.
//C code
//This program will calculate the average speed of passing cars using a WHILE-END loop
//Developer: Jasmine Tucker
//Date: 7 Sept 2014
#include <stdio.h>
/* define variable */
//You Can define global variables or local variables. If you want to use them outside your
//function you Need to declare them globally as done here
int average_speed;
int car_count;
int car_speed;
//This is where the Magic happens. If you execute your program it will jump to the main
//function and execute whatever is in there
int main ()
{
/* set variable values */
average_speed= 0;
car_count=0;
car_speed=0;
/*WHILE-END loop */
//The while Loop is not a function, you Need to put it in main() so it gets executed
while(car_count > 0)
{
//You did use very strange signs here. The correct ones are These: ""
printf("Enter the car’s speed %s:", car_count);
scanf("%d", &car_speed);
average_speed= car_speed / car_count; //You Forget a semicolon indeed ;-)
car_count++;
}
printf("\n The average speed is %d miles per hour. \n", average_speed);
return 0;
} //semicolons at the end of a function are not used in C. They are used if you want to define a structure.
I strongly suggest that you start off with basic books / a wiki to C programming. Here is a good (at least it was for me) start into that: http://en.wikibooks.org/wiki/C_Programming/Intro_exercise

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