This works
main()
{
int c;
struct books Book1;
c = getchar( );
return 0;
}
This doesn't
main()
{
int c;
c = getchar( );
struct books Book1;
return 0;
}
Expression syntax in function main (and points to the space after the word 'struct')
This doesn't either because the definition of B is below c = getchar();, error points to the space between "int" and "b"
main()
{
int c;
struct books Book1;
c = getchar( );
int b;
return 0;
}
Is the problem that i have to define every variable before calling functions, or is it something else?
Is this how C works, or is it a turbo C thing?
Edit: found duplicates after realizing that i meant to say "definition" not "declaration"
Where you can and cannot declare new variables in C?
Can't define variables after a function call
In C89, variables must be declared in the beginning of a block. The restriction was removed since C99.
It's not a surprise that Turbo C, an outdated compiler, doesn't support this C99 feature.
Related
In the program i have not mentioned return type for function fullon but the code still runs and output: "7" is printed. How did this works even when i did not mentioned any return type? i have searched it on this site and i am not able to find any suitable answer.I am still a beginner so i don't have much background of C.
#include<stdio.h>
fullon(int);
int main()
{
int b;
int x = 5 ;
b = fullon(x);
printf("%d" , b);
}
fullon(int y)
{
return y+2;
}
Update 1 :
#include<stdio.h>
fullon(float);
int main()
{
float b;
int x = 5 ;
float f = 3.5;
b = fullon(f);
printf("%f" , b);
}
fullon(float y)
{
return y;
}
Output is 3.000000
Back in the 1980s, pre-standard C (sometimes called K&R C, where K&R refers to the names of Kernighan and Ritchie, who created the language and wrote the first C language manual) allowed function declarations like this one:
noreturntype()
{
//returns something the size of an int
/* do something */
return 456;
}
So even though the function had no return type, it was allowed to return anything that had the same number of bytes as an int on a given implementation. (For instance, if a 16-bit machine had 16-bit integers and 16-bit pointers, it was allowed to return either an int or a pointer in such a function.)
When the C standard was created, these old-style declarations were kept for backwards compatibility with existing programs. (As a matter of fact, even modern compilers tend to accept old-style function declaration along with a warning).
In C, functions have an implied return type of int if it's not specified. This is an ancient quirk and absolutely should not be used; I'm surprised your compiler isn't giving you a warning about it.
From my memory, mangling name is not used in C, which is kinda of a feature that we take advantage using C function for ABI (Application Binary Interface). But recently I have been reading this article about mangling name in C
https://gustedt.wordpress.com/2011/06/24/name-mangling-in-c/
Question here is, If in any case that compiler will mangle C function name?
Since C is a programming language that does not support name function overloading, it does no name mangling. But for compilers targeted at Microsoft Windows Platform, which has a variety of calling conventions like _cdecl,_stdcall etc. the function names are mangled to provide information regarding the calling convention.
For example,
int _stdcall fun(int myVar) {return 0;}
int _fastcall fun(int myVar){return 1;}
int _cdecl fun(int myVar){return 2;}
the compiler(32-bit) output will be like this:
_fun#4 /* _(function_name)#(argument_size_in_bytes) */
#fun#4 /* #(function_name)#(argument_size_in_bytes) */
_fun /* _(function_name) */
Function names won't be mangled, except apparently in the case of Unicode identifiers. For example:
// Mangled as "o_u03ba" using Intel's compiler "icc").
extern int o\u03ba(void);
The issue with icc highlighted by the blog article linked in the question is obviously a problem when the compiler generates non-unique symbol names:
//Both will have the same symbol name.
extern void o\u03ba(volatile int *p)
{
*p = -32767;
}
extern void o_u03ba(volatile int *p)
{
*p = 0;
}
...
volatile int n;
// Should print -32767; may print 0 or -32767.
o\u03ba(&n);
printf("%d\n", n);
// Should print 0; will print the same thing as the previous line.
o_u03ba(&n);
printf("%d\n", n);
Functions declared with the static keyword have internal linkage. Despite this, the compiler's internal representation may still use a mangled name, though you will never see it in the resulting program. When resolving references to functions, however, the code presented by the article indicates that even using the name at all can cause an issue:
static void foo\u03ba(volatile int n)
{
printf("foo\\u03ba: n = %d\n", n);
}
static void foo_u03ba(volatile int n)
{
printf("foo_u03ba: n = %d\n", n);
}
...
volatile int n = 10;
// These two lines may print the same thing.
foo\u03ba(n);
foo_u03ba(n);
Since you technically cannot take the address of a function and print it reliably, the best you can do is uniquely identify which function is called.
I am reading a book on the C language ('Mastering C'), and found the topic on scope resolution operator (::) on page 203, on Google Books here.
But when I run the following code sample (copied from the book), the C compiler gives me an error. I searched on the internet but I am unable to find any reference to a scope resolution operator in C.
#include <stdio.h>
int a = 50;
int main(void)
{
int a =10;
printf("%d",a);
printf("%d\n", ::a);
return 0;
}
So if I want to access a global variable then how could I do that from within the main() function ?
No. C does not have a scope resolution operator. C++ has one (::). Perhaps you are (or your book is) confusing C with C++.
You asked how you could access the global variable a from within a function (here main) which has its own local variable a. You can't do this in C. It is lexically out of scope. Of course you could take the address of the variable somewhere else and pass that in as a pointer, but that's a different thing entirely. Just rename the variable, i.e. 'don't do that'
No, namespaces are a feature of C++.
It is, however, possible to refer to global a in your example.
You can achieve this by using the extern keyword:
#include <stdio.h>
int a = 50;
int main(void)
{
int a = 10;
printf("%d\n",a);
{ // Note the scope
extern int a; // Uses the global now
printf("%d\n", a);
}
return 0;
}
That's a bit tricky, though. It's bad style. Don't do that.
:: operator is available in C++ not C. If you wanted to access the global variable, use
#include <stdio.h>
int a = 50;
int main(void)
{
int a =10;
printf("%d",a); //prints 10
{
extern int a;
printf("%d", a); //prints 50
}
return 0;
}
Or you could use a pointer which holds the address of the global variable a and then dereference the pointer if you want to print the value of the global variable a.
No (the :: operator is C++ specific). In C, if you use the same identifier in different overlapping scopes (say, file scope a and block scope a), the block scope identifier shadows the file scope identifier and there is no way to refer to the shadowed identifier.
It is generally best programming practice to avoid shadowed variables. Many lint type programs can warn about this situation.
In plain C, there is no scope resolution. You have to name your variables differently.
That means that all variables a below are different ones:
#include <stdio.h>
int a = 50;
int main(void)
{
int a = 10;
{
int a = 20;
int i;
for (i = 0; i < 10; i++) {
int a = 30;
}
}
return 0;
}
You may use pointers to access and edit global variables in C.
#include <stdio.h>
#include <stdlib.h>
int a;
a=78;
int *ptr=&a; //pointer for global a
int main()
{
int a=0;
printf("%d",a); //Prints 0 as local variable
printf("%d",*ptr);
ptr=30; //changes the value of global variable through pointer
printf("%d",*ptr); //Now it prints 30
return 0;
}
It entirely depends on what kind of compiler you're using to execute your code.
#include <stdio.h>
int a = 50;
int main(void)
{
int a =10;
printf("%d\n",a);
printf("%d\n", ::a);
return 0;
}
Try running this code in Turbo C compiler, and you will get the results.
Now, regarding the C book that you're following, the examples codes present in the book must be in terms with Turbo C/C++ compiler and not the gcc compiler.
In the beginning of chapter 6: Structures of the book by Brian W. Kernighan and Dennis M. Ritchie, there is a paragraph that I can't understand.
The main change made by the ANSI standard is to define structure assignment - structures may be copied and assigned to, passed to functions, and returned by functions. This has been supported by most compilers for many years, but the properties are now precisely defined. Automatic structures and arrays may now also be initialized.
What does it mean that automatic structures and arrays may now also be initialized? I'm pretty sure that automatic, namely local variables should be initialized manually. Would you please help me understand what it means?
In pre-standard C (meaning 'before the C89 standard', or a long time ago), you could not write:
int function(int i)
{
int array[4] = { 1, 2, 3, 4 };
struct { int x; int y; } x = { 1, 2 };
struct { int x; int y; } a[] = { { 2, 3 }, { 3, 4 } };
...code using array, x, a...
return x.y + a[!!i].x + array[3];
}
Now you are allowed to do all these.
Also, in K&R 1st Edition C (circa 1978), you were not allowed to write:
int another()
{
struct { int x; int y; } a, b;
a.x = 1;
a.y = 0;
b = a; /* Not allowed in K&R 1 */
some_other_func(a, b); /* Not allowed in K&R 1 */
some_other_func(&a, &b); /* Necessary in K&R 1 */
...
}
You could also only return pointers to structures (as well as pass pointers to structures). IIRC, some C compilers actually allowed the non-pointer notation, but converted the code behind the scenes to use pointers. However, the structure assignment and structure passing and structure returning limitations were removed from C well before the standard (shortly after K&R 1 was published). But not all compilers supported these features because there wasn't a standard for them to conform to.
It means you can do stuff like this:
typedef struct { int a; float b; } foo;
int main(void) {
foo f = { 42, 3.14 }; // Initialization
...
}
While programming I have come to an unusual error. When I initialize an integer in a loop, sometimes it says that the expression is not valid, but at times it accepts it.
This is my code which gives error:
int pow(int x,int n);
int main()
{
int x,n,result;
printf("Enter a number:\n");
scanf("%d",&x);
printf("Enter its power:\n");
scanf("%d",&n);
result=pow(x,n);
printf("Result is %d\n",result);
getch();
return 0;
}
int pow(int x,int n)
{
for(int i=1;i<n;i++) //<-- here it says that declaration syntax error
x=x*i;
return x;
}
While when i change it like this :
int pow(int x,int n)
{
int i;
for(i=1;i<n;i++)
x=x*i;
return x;
}
C89 and earlier versions only support declaration statements at the head of a block (IOW, the only thing that can appear between an opening { and a declaration is another declaration):
/* C89 and earlier */
int main(void)
{
int x; /* this is legal */
...
for (x = 0; x < 10; x++)
{
int i; /* so is this */
printf("x = %d\n", x);
int j = 2*x; /* ILLEGAL */
}
int y; /* ILLEGAL */
...
}
With C99, declaration statements can appear pretty much anywhere, including control expressions (with the caveat that something must be declared before it is used):
// C99 and later, C++
int main(void)
{
int x; // same as before
...
for (int i = 0; i < 10; i++) // supported as of C99
{
printf("i = %d\n", i);
int j = 2 * i; // supported as of C99
}
int y; // supported as of C99
}
Turbo C predates the C99 standard, so if you want to write code like in the second example, you will need to use a more up-to-date compiler.
In C, before C99, you need to declare your variables before your loop. In C++, and now in C99, you can declare them within the loop as you try here. The different results you are getting may be because you are sometimes compiling as C++, and sometimes compiling as C.
You could try to make sure you are always compiling your code as C++, or if you're using GCC or Clang, compile with the --std=c99 flag. C99 is unsupported by MSVC, so you will either need to use C++ or move the declaration outside of the loop if you're using MSVC.
It sounds like you have a C89 compiler (rather than C99 compiler).
In C89, you are only allowed to declare variables at the beginning of a function. You are simply not allowed to declare variables elsewhere in a function, including in the initialization part of a for statement. That's why the second syntax works and the first fails.
The second syntax is valid for C99 and C++ but not for C89.
What C compiler are you using?
Older versions of C prior to C99 require all variable declarations be made at the top of a code block.