C: why do I get invalid initializer? - c

I have to do a function which returns the dot product of two vectors.
Here his the code:
float res;
float v1[3];
float v2[3];
v1[0] = 3;
v1[1] = 2;
v1[2] = 0;
v2[0] = 2;
v2[1] = 5;
v2[2] = 0;
float dotProd(float *vec1, float *vec2) {
return vec1[0]*vec2[0] + vec1[1]*vec2[1] + vec1[2]*vec2[2];
}
res = dotProd(v1, v2)
I thik the function is right, the problem is that I get invalid initializer error when I define the values of the vectors.
What am I missing?

What you are attempting to do is not initialization but assignment. The former is done at the time the variable is defined, while the later is done later as an executable statement. You're getting an error because executable statements are not allowed outside of a function.
You need to use an initializer at the time the arrays are defined:
float v1[3] = {3, 2, 0};
float v2[3] = {2, 5, 0};

float v1[3];
// ...
v1[0] = 3;
v1[1] = 2;
v1[2] = 0;
This: float v1[3]; is a declaration (and a definition). It defines an array object named v1. It can legally appear either at file scope (outside any function) or at block scope (inside a function definition).
This: v1[0] = 3; is a statement. Statements are permitted only inside a function definition.
If you want those statements to be executed just once, you can put them inside your main function.
Execution of your program begins with an implicit call to your main function. Very nearly everything that happens as your program runs results from that, as other functions are called from main, directly or indirectly. If you could have statements outside any function, there would be no way for them ever to be executed. File-scope declarations are permitted, but they're restricted to ones that don't execute any code. For example, a declaration like:
int n = 42;
is permitted either at file scope or at block scope; if it's at file scope the value 42 is loaded into n at program startup. But if the initializer isn't a constant expression, such as:
int r = rand();
then it can only appear at block scope; there's no way to call a function before main starts.
As for why you're getting that particular message, the compiler's parser isn't expecting to see a statement in that context, so it tries (and fails) to interpret v1[0] = 3; as a declaration. When a compiler sees something that's syntactically invalid, it tries to interpret it in a way that lets it give a meaningful error message, but it doesn't always succeed.

Your code is fine; you are probably just having a structure problem.
Try something like:
#include<stdio.h>
float dotProd(float * vec1, float * vec2) {
return vec1[0] * vec2[0] + vec1[1] * vec2[1] + vec1[2] * vec2[2];
}
int main() {
float res;
float v1[3];
float v2[3];
v1[0] = 3;
v1[1] = 2;
v1[2] = 0;
v2[0] = 2;
v2[1] = 5;
v2[2] = 0;
res = dotProd(v1, v2);
printf("%lf", res);
return 0;
}

Related

Called function work at printf but not at arithmetic statement

I made a struct Triangle and I made a function to calculate p(perimeter/2).
When I call the function inside printf it works.
But when I call the same function as a simple arithmetic statement it doesn't work and gives me following error
called object 'p' is not a function or function pointer
Source code:
#include <stdlib.h>
typedef struct{
int a, b, c;
} Triangle;
int perimeter (Triangle t){
return t.a + t.b + t.c;
}
float p (Triangle t){
return perimeter(t) / 2.0;
}
int main() {
Triangle t = {3, 4, 5};
//float p = p(t);
printf("p = %.2f\n",p(t));
return 0;
}
//float p = p(t);
You cannot use the same name for a function and a variable. Change your float p to float a and it should work. Or rename your function to, say perimeter instead of just p.
Also in general, it is better to use slightly longer, clear and descriptive names for functions.
The line
float p = p(t);
defines a local variable p which shadows the global function p. This variable is of type float, so it is not a function or pointer.
Rename the variable to fix this.

Why does the int keyword have an effect on the variable value when changing a variable

If I do something like this:
int a = 1;
int b = 2;
a = a + b;
a gives 3 in this instance, however if I do something like this:
int a = 1;
int b = 2;
int a = a + b
a gives a very large number (1827585825)
Can anyone explain why this occurs?
Redefinition of variable as you attempted is not allowed in C, and fails to compile. However, a slightly modified version of your code does compile:
int main() {
int a = 1;
int b = 2;
{
int a = a + b;
// use a
}
return 0;
}
int a = a + b is valid, but doesn't mean what you think it does. The a in a + b refers to the inner and as-yet uninitialized variable a, and not to the outer a. Using it in an expression is undefined behavior and results in garbage output.
Your code is invalid and it will not compile at all.
The second a definition has to be in a different scope like in the example below.
#include <stdio.h>
int a = 1;
int b = 2;
int main(void)
{
int a = a + b; //declares new a variable which has undetermined value
}
The second definition of a hides the global one and newly defined int variable will not be initialized. You take this not initialized variable (having undetermined value) and add another value to it. The result will also undetermined. It is Undefined Behaviour.
https://www.tutorialspoint.com/cprogramming/c_scope_rules.htm

Do cycles have their own stack record? (aka why is this code legal)

Ok, so I'm having a little question for you here.
I'm going to write code in C, but I guess this would work just the same in most languages.
So, why is this code legal:
int x = 1;
while(true) {
int x = x + 2;
}
While this calls for error: redefinition of ‘x’
int x = 1;
int x = 3;
So, I am aware that I'd be able to use the same name for a variabile in different functions within my program, since each function call would have its own stack record.
But do cycles have their own stack records as well? On a memory level, code #1 doesn't result in me having N different associactions for the variable x within the same stack record block?
In short, why in code #2 I'm redefining the x variable, but in code #1 I am not?
The two variables are declared in different scope.
int x = 1;
while(true) {
int x = x + 2;
}
The variable declared in the inner scope hides the variable declared in the outer scope.
Pay attention to that this declaration
int x = x + 2;
has undefined behavior because the declared variable is used itself as an initializer though it was not initialized.
For example you can write
int x = 1;
int main( void )
{
int x = 2;
while ( 1 )
{
int x = 3;
/*...*/
}
}
In this program there are declared and defined three different objects with the name x.
The first variable has the file scope while the other two have block scopes.
As for this code snippet
int x = 1;
int x = 3;
two variables in the same scope are defined with the same name.
In C (but not in C++) you may write
#include <stdio.h>
int x;
int x = 1;
int main(void)
{
return 0;
}
because in the file scope this
int x;
is not a definition of the variable x but is only its declaration.
Also you may write for example
#include <stdio.h>
int x;
int x = 1;
int main(void)
{
extern int x;
printf( "x = %d\n", x );
return 0;
}
The line
extern int x;
introduces the declaration of the global variable x in the block scope of main.
As for the while statement then (The C STandard, 6.8.5 Iteration statements
)
5 An iteration statement is a block whose scope is a strict subset of
the scope of its enclosing block. The loop body is also a block whose
scope is a strict subset of the scope of the iteration statement.

Declaring a variable in C

I’m having a hard time with declaring my variables within C. The compiler display a message “expected constructor destructor or type conversion before token.” What am I doing wrong?
#include <stdio.h>
int count =0;
int abc;
ABC;
a = 19, b = 27, c = 3;
a = 4 + 5 * 3;
b = (4 +5) * 3;
c = 25 -(2 * (10 + (8 / 2)));
main {
printf("Enter a value please\n");
scanf("%d, , \n");
return 0;
}
Here's a rewrite, showing how to fix the various issues:
#include <stdio.h>
int count = 0; // declarations and intitializations are allowed at file
// scope (that is, outside of any function body). The
// storage for count will be set aside at program start
// and held until the program terminates.
//
// count is visible to all functions defined within this
// file, and will be visible to other files compiled and
// linked into the same program.
int main( void ) { // Implicit typing of functions is no longer allowed as of C99,
// and it was never good practice to begin with.
// IOW, the compiler will not assume a return type of
// int if a type specifier is missing. main always
// returns int, and either takes 0 or 2 arguments.
int a, b, c; // int abc; declares a *single* variable named "abc",
// not three variables named "a", "b", and "c".
// Storage for these variables will be set aside at
// function entry and held until the function exits.
//
// None of a, b, or c are visible outside of the
// function body.
// ABC has not been defined anywhere; it's not clear
// what the intent was behind ABC;
a = 19; // While not illegal, a = 19, b = 27, c = 3; is not the best style
b = 27; // in the world; it's better to make these three separate statements
c = 3; // Note that assignment statements (like any other executable
// statement) are not allowed outside of a function body.
a = 4 + 5 * 3; // fine
b = (4 +5) * 3; // fine
c = 25 -(2 * (10 + (8 / 2))); // fine
printf("Enter a value please\n"); // fine
scanf("%d", &a); // Each conversion specifier in a scanf call needs a corresponding
// argument to write the input value to, and the argument needs
// to be of the correct type. %d expects the corresponding
// argument to have type "int *" (pointer to int). The expression
// "&a" gives the address of the variable "a", and the type
// of the expression is "int *". So, this statement will read an
// integer value from standard input and store it to a.
return 0;
}
You cannot write assignments like a = 19, b = 27, c = 3; outside functions.
int count = 0; is the initialisation of a global variable, so that is allowed.
ABC; is also meaningless unless ABC has been #defined to something numerical, and even then it would be a no-op.
main is also malformed. You need to write it as int main() and make sure you return a value.
Lastly, your scanf argument list is not correct. Do consult the documentation.
It would be a good idea to study an introduction to C. Kernighan & Ritchie is an excellent book.

c: Style: altering variables in place

Suppose we have something along these lines
int f(int n);
....
do{
int a = b;
int b = f(a);
}
Is there any risk to saying
do{
int b = f(b);
}
instead, assuming a is not used elsewhere? Would it be stylistically preferable to do the former?
It is important to understand that you're not "altering" any variables here, just changing the meaning of a name.
The important concept is called the point of declaration.
Let's look at your example:
int b = 42;
{
int a = b;
int b = 23 * a;
printf("%d\n", b);
}
printf("%d\n", b);
or
int b = 42;
{
int b = 23 * b;
printf("%d\n", b);
}
printf("%d\n", b);
The name b references two objects, depending on where you are in the code, let's call them b1 and b2. This is unsurprising in case 1:
int b1 = 42;
{
int a = b1;
int b2 = 23 * a;
printf("%d\n", b2);
}
printf("%d\n", b1);
Since in C the point of declaration is before the initializer, the second example resolves differently:
int b1 = 42;
{
int b2 = 23 * b2;
printf("%d\n", b2);
}
printf("%d\n", b1);
Note that here there's no link between b1 and b2, you're initializing b2 with its own (undefined) value. A diligent compiler will warn you about this, like
x.c:7:13: warning: 'b' is used uninitialized in this function [-Wuninitialized]
As the compiler parses C code it populates a symbol table, this table contains information about all the different symbols and by symbols I mean identifiers, such as the names you give your variables, functions, and so forth ...
Most C programs are constructed out of nested scopes, global -> function -> component_statements and so on, each scope usually has its own symbol table, so the compiler uses a stack of symbol tables to keep track of everything, when a variable is looked up but isn't defined in the current symbol table it starts the search by going upward the stack until it hits global or usually last table ... but as soon one is defined in the current scope an entry is made 'shadowing' the previous.
heres a simple program to illustrate.
#include <stdio.h>
/* global accessable by most things ... */
int a = 5;
int main()
{ /* function scope */
int a = 4; /* shadowing global */
{ /* nested scope within function scope */
int b = a;
int a = b; /* shadowing function */
printf("%i\n", a);
}
return 0;
}
if you run this you would get 4 which is to be expected but anyone following your code would have to keep in the back of their mind that a is different from all the other a from global, function main ... If the programmer maintaining the code isn't aware of this things or you yourself forgot then you can have subtle run-time bugs that can be quite hard to debug ...
also note that if you run this:
#include <stdio.h>
/* global accessable by most things ... */
int a = 5;
int main()
{ /* function scope */
int a = 4; /* shadowing global */
{ /* nested scope within function scope */
int a = a; /* shadowing function, but not actually accessing outer scope */
printf("%i\n", a);
}
return 0;
}
you wouldn't get 4 but some large random int on my machine its 1606422610 since the variable is being assigned to itself that was just shadow, and c doesn't initialize variables.

Resources