I am getting a strange error that's saying that my variables are not declared even though I have declared them in main. Am I missing something?
Error 4 error C2065: 'destination' : undeclared identifier c:\users\owner\documents\visual studio 2012\projects\project36\project36\source.c 26 1 Project36
I am programming in C.
variable declaration:
char sourcePiece;
char destination;
function call:
askForMove(sourcePiece, destination);
function def:
void askForMove(char sourcePiece, char destination) {
char sourcePiece;
char destination;
printf("\nEnter your desired move. First enter the starting position, followed by the ending position in letters: ");
scanf(" %c %c", &sourcePiece, &destination);
}
prototype:
void askForMove(char, char );
As it has been noted by some commenters, one of the problems is that you cannot have a local variable and a formal parameter with the same name. I suggest that you remove the declarations of the local variables, because it's the parameters that you want to use in your function, not them.
The full version of the code and the latest screenshot with the errors that you posted indicate that the compiler complains about the local variable declarations made in main function. The compiler complains because the variable declarations are interleaved with statements inside main, which was not supported by "classic" C language (C89/90). In order to compile this code you need a C99 (or later) compiler.
The code is easy to fix for a pre-C99 compiler - just move all local variable declarations to the beginning of the enclosing block (i.e. to the beginning of main in your case).
You Should Know that
Formal parameters, are treated as local variables within a function.
So Here You are duplicating them and it is causing error.
void askForMove(char sourcePiece, char destination) {
char sourcePiece; //Redeclaring already present in formal parameter.
char destination; //Redeclaring already present in formal parameter.
printf("\nEnter your desired move. First enter the starting position, followed by the ending position in letters: ");
scanf(" %c %c", &sourcePiece, &destination);
}
Remove Them
void askForMove(char sourcePiece, char destination) {
printf("\nEnter your desired move. First enter the starting position, followed by the ending position in letters: ");
scanf(" %c %c", &sourcePiece, &destination);
}
Also Note your question is not a good example of how one should write , Always Post Minimal, Complete, and Verifiable example.
Update
What AnT is saying make sense , see this C89, Mixing Variable Declarations and Code
I'm not sure what you intended to achieve in your program but you have a duplication in your variable names. Don't use the same name for the function argument and the local variable.
Related
I use Visual Studio 2022, which marks scanf() function as unsafe and deprecates it. It recommends me to use scanf_s() instead.
So yesterday my teacher was teaching us strings in C and showed us a program to receive a string from the keyboard which I tried out in my compiler
Using scanf_s() to input a string returned error C4473 or C6064 even though my code was identical to that of my teacher's aside from the scanf() difference.
#include<stdio.h>
#include<stdlib.h>
void main() {
char name[25];
printf("Enter your name ");
scanf_s("%s", name);//gave an ERROR
printf("Hello %s!", name);
}
I tried using the regular scanf() along with disable warning and it worked.
#include<stdio.h>
#include<stdlib.h>
#pragma warning(disable : 4996)
void main() {
char name[25];
printf("Enter your name ");
scanf("%s", name);//worked as intended
printf("Hello %s!", name);
}
Why does scanf_s fail take string inputs?
From the C Standard *K.3.5.3.2 The fscanf_s function) This description is the same as for the function scanf_s
4 The fscanf_s function is equivalent to fscanf except that the c, s,
and [ conversion specifiers apply to a pair of arguments (unless
assignment suppression is indicated by a *). The first of these
arguments is the same as for fscanf. That argument is immediately
followed in the argument list by the second argument, which has type
rsize_t and gives the number of elements in the array pointed to by
the first argument of the pair. If the first argument points to a
scalar object, it is considered to be an array of one element.
So you need to write
scanf_s( "%s", name, sizeof( name ) );
Also this call of scanf
scanf("%s", name);
will be safer if to rewrite it like
scanf( "%24s", name );
Pay attention to that according to the C Standard the function main without parameters shall be declared like
int main( void )
This is the declaration of a variable printf:
int printf=90;
This runs without any error , but if I try to print the value of the identifier with the given name printf , then it gives error , so why is it that although the compiler is allowing printf to be used as an identifier but we can't later print its value .
Your question is a bit mixed up.
C has "scope rules", that govern how a name (like printf) is resolved from a given point in the code. It's possible, and legal according to the scope rules, to shadow a name from an outer scope.
Typically printf is extern-declared from <stdio.h>, and its value is replaced by the proper function address from the standard library by the linker.
But if you declare a new variable like that, you are shadowing the name. Basically you get a new variable of a new type, with the same name as an existing one. The outer, original, printf then becomes unreachable from that scope, since C doesn't have a scope resolution operator. In C++, you could use ::printf which always references the global printf. C doesn't have that.
You can work around it by copying the original value of printf before shadowing it:
{
int (*theprintf)(const char *fmt, ...) = printf;
int printf = 90;
theprintf("now printf has the value %d\n", printf);
}
As mentioned in a comment, once you're done with your local variant you can re-declare it as extern to get it back, but you can't do that in the same scope:
{
extern int printf(const char * fmt, ...);
printf("hello?\n");
}
#include<stdio.h>
int main()
{
int i = 10;
printf("0 i %d %p\n",i,&i);
if (i == 10)
goto f;
{
int i = 20;
printf("1 i %d\n",i);
}
{
int i = 30;
f:
printf("2 i %d %p\n",i,&i); //statement X
}
return 0;
}
Output:
[test]$ ./a.out
0 i 10 0xbfbeaea8
2 i 134513744 0xbfbeaea4
I have difficulty in understanding how statement X works?? As you see the output it is junk. It should rather say i not declared??
That's because goto skips the shadowing variable i's initialization.
This is one of the minor nuances of the differences between C and C++. In strict C++ go to crossing variable initialization is an error, while in C it's not. GCC also confirms this, when you compile with -std=c11 it allows while with std=c++11 it complains: jump to label 'f' crosses initialization of 'int i'.
From C99:
A goto statement shall not jump from outside the scope of an identifier having a variably modified type to inside the scope of that identifier.
VLAs are of variably modified type. Jumps inside a scope not containing VM types are allowed.
From C++11 (emphasis mine):
A program that jumps from a point where a variable with automatic storage duration is not in scope to a point where it is in scope is ill-formed unless the variable has scalar type, class type with a trivial default constructor and a trivial destructor, a cv-qualified version of one of these types, or an array of one of the preceding types and is declared without an initializer.
From the output, it is clear that the address of 'i's are unique, since they are declared in different scopes.
0 i 10 0xbfbeaea8
2 i 134513744 0xbfbeaea4
how statement X works?? As you see the output it is junk. It should
rather say I not declared??
i is also declared in the local scope of statement x but the initialization of i to 30 is skipped because of goto statement. Therefore the local variable i contains a garbage value.
In the first printf statement, you accessed the i in address 0xbfbeaea8 which was declared and initialized in the statement int i = 10;
Once you hit the goto f; statement, you are in the scope of the 2nd i, which is declared at this point and resides in address 0xbfbeaea4 but which is not initialized as you skipped the initialization statement.
That's why you were getting rubbish.
When control reaches the third block, i is declared for the compiler, hence i represents some memory address therefore compiler tries to read it again. But since i has now become out-of-scope, you cannot be sure that it will contain the same value what it originally had.
My suggestion to understand somewhat complex code is to strip out, one by one, all "unnecessary" code and leave the bare problem. How do you know what's unnecessary? Initially, when you're not fluent with the language, you'll be removing parts of the code at random, but very quickly you'll learn what's necessary and what is not.
Give it a try: my hint is to start removing or commenting out the "goto" statement. Recompile and, if there are no errors, see what changed when you run the program again.
Another suggestion would be: try to recreate the problem "from scratch": imagine you are working on a top-secret project and you cannot show any single line of code to anyone, let alone post on Stack Overflow. Now, try to replicate the problem by rewriting equivalent source code, that would show the same behaviour.
As they say, "asking the right question is often solving half the problem".
The i you print in this printf("2 i %d %p\n",i,&i); statement, is not the i which value was 10 in if statement, and as you skip this int i = 30; statement with goto you print garbage. This int i = 30; is actual definition of the i that would be printed, i.e. where compiler allocates room and value of i.
The problem is that your goto is skipping the assignment to the second i, which shadows (conceals) the first i whose value you've set, so you're printing out an uninitialized variable.
You'll get a similar wrong answer from this:
#include<stdio.h>
int main()
{
int i = 10; /* First "i" */
printf("0 i %d %p\n",i,&i);
{ /* New block scope */
int i; /* Second "i" shadows first "i" */
printf("2 i %d %p\n",i,&i);
}
return 0;
}
Three lessons: don't shadow variables; don't create blocks ({ ... }) for no reason; and turn on compiler warnings.
Just to clarify: variable scope is a compile-time concept based on where variables are declared, not something that is subject to what happens at runtime. The declaration of i#2 conceals i#1 inside the block that i#2 is declared in. It doesn't matter if the runtime control path jumps into the middle of the block — i#2 is the i that will be used and i#1 is hidden (shadowed). Runtime control flow doesn't carry scope around in a satchel.
int main()
{
int j=97;
char arr[4]="Abc";
printf(arr,j);
getch();
return 0;
}
this code gives me a stack overflow error why?
But if instead of printf(arr,j) we use printf(arr) then it prints Abc.
please tell me how printf works , means 1st argument is const char* type so how arr is
treated by compiler.
sorry! above code is right it doesn't give any error,I write this by mistake. but below code give stack overflow error.
#include <stdio.h>
int main()
{
int i, a[i];
getch();
return 0;
}
since variable i take any garbage value so that will be the size of the array
so why this code give this error when i use DEV C++ and if I use TURBO C++ 3.0 then
error:constant expression required displayed. if size of array can't be variable then when
we take size of array through user input.no error is displayed. but why in this case.
please tell me how printf works
First of all, pass only non-user supplied or validated strings to the first argument of printf()!
printf() accepts a variable number of arguments after the required const char* argument (because printf() is what's called a variadic function). The first const char* argument is where you pass a format string so that printf() knows how to display the rest of your arguments.
If the arr character array contains user-inputted values, then it may cause a segfault if the string happens to contain those formatting placeholders, so the format string should always be a hard-coded constant (or validated) string. Your code sample is simple enough to see that it's really a constant, but it's still good practice to get used to printf("%s", arr) to display strings instead of passing them directly to the first argument (unless you absolutely have to of course).
That being said, you use the formatting placeholders (those that start with %) to format the output. If you want to display:
Abc 97
Then your call to printf() should be:
printf("%s %d", arr, j);
The %s tells printf() that the second argument should be interpreted as a pointer to a null-terminated string. The %d tells printf() that the third argument should be interpreted as a signed decimal.
this code gives me a stack overflow error why?
See AndreyT's answer.
I see that now the OP changed the description of the behavior to something totally different, so my explanation no longer applies to his code. Nevertheless, the points I made about variadic functions still stand.
This code results in stack invalidation (or something similar) because you failed to declare function printf. printf is a so called variadic function, it takes variable number of arguments. In C language it has [almost] always been mandatory to declare variadic functions before calling them. The practical reason for this requirement is that variadic functions might (and often will) require some special approach for argument passing. It is often called a calling convention. If you forget to declare a variadic function before calling it, a pre-C99 compiler will assume that it is an ordinary non-variadic function and call it as an ordinary function. I.e. it will use a wrong calling convention, which in turn will lead to stack invalidation. This all depends on the implementation: some might even appear to "work" fine, some will crash. But in any case you absolutely have to declare variadic functions before calling them.
In this case you should include <stdio.h> before calling printf. Header file <stdio.h> is a standard header that contains the declaration of printf. You forgot to do it; hence the error (most likely). There's no way to be 100% sure, since it depends on the implementation.
Otherwise, your code is valid. The code is weird, since you are passing j to printf without supplying a format specifier for it, but it is not an error - printf simply ignores extra variadic arguments. Your code should print Abc in any case. Add #include <stdio.h> at the beginning of your code, and it should work fine, assuming it does what you wanted it to do.
Again, this code
#include <stdio.h>
int main()
{
int j=97;
char arr[4]="Abc";
printf(arr,j);
return 0;
}
is a strange, but perfectly valid C program with a perfectly defined output (adding \n at the end of the output would be a good idea though).
In your line int i, a[i]; in the corrected sample of broken code, a is a variable-length array of i elements, but i is uninitialized. Thus your program has undefined behavior.
You see strings in C language are treated as char* and printf function can print a string directly. For printing strings using this function you should use such code:
printf("%s", arr);
%s tells the function that the first variable will be char*.
If you want to print both arr and j you should define the format first:
printf("%s%d", arr, j);
%d tells the function that the second variable will be int
I suspect the printf() issue is a red herring, since with a null-terminated "Abc" will ignore other arguments.
Have you debugged your program? If not can you be sure the fault isn't in getch()?
I cannot duplicate your issue but then I commented out the getch() for simplicity.
BTW, why did you not use fgetc() or getchar()? Are you intending to use curses in a larger program?
===== Added after your edit =====
Okay, not a red herring, just a mistake by the OP.
C++ does allow allocating an array with the size specified by a variable; you've essentially done this with random (garbage) size and overflowed the stack, as you deduced. When you compile with C++ you are typically no longer compiling C and the rules change (depending on the particular compiler).
That said, I don't understand your question - you need to be a lot more clear with "when we take size of array through user input" ...
I have the following C code in a program:
printf("Test before print_foo()");
void print_foo(char board[ROW][COL]);
printf("Test after print_foo()");
where print_foo printf's the passed in 2-D character array with proper .c and .h files imported.
Console output is only the two printf statements.
Debugging, the run-time never even steps into print_foo.
Any ideas?
That void prefix is making the middle line into a declaration of function print_foo (and the char within the parentheses means it would be invalid syntax otherwise). To just call print_foo, change the middle line to print_foo(board); (if board is how you named that 2-D character array).
That looks like a function declaration to me - that's why your foo-nction is not being called.
Your middle line is just a function declaration, not a function call.
If you didn't declare the prototype previously then you have to write this :
printf("Test before print_foo()");
void print_foo(char board[ROW][COL]);
print_foo(board);
printf("Test after print_foo()");
In short you have to define/declare print_foo before invoking,or your compiler will flag an error !!
void print_foo(char board[ROW][COL]);
is not a function call. It's a declaration.
You probably want
print_foo(board);