Is this practice of manually applying scopes standard C? - c

Is creating local scopes with just a pair of brackets, would that be considered standard C?
#include <stdio.h>
int main(int argc, char *argv[]) {
{
register char x = 'a';
putchar(x); // works
}
//putchar(x); wont work
}
Or is it best to not use this? Is it a GCC compiler extension?
I have once been told that the accepted practice is a do {...} while (0); loop. Is it true that all C compilers will recognise this practice just like it is safe to assume any given C compiler will recognise an if statement?
I tried googling this, and my results were about scope behavior, and had nothing to do with manually applying scopes.

Yes, it is standard; this is creation of block scope, as supported by C language.
Regarding "best to use" part, it depends, certainly it might be a bit confusing to some people.
This might come in very useful with generated code though, so you don't need to bother (as much) with unique identifiers for local vars:
int main(int argc, char *argv[]) {
{
int x = 4;
printf("%d\n", x);
}
{
int x = 5;
printf("%d\n", x);
}
}

Yes, it is standard; you can always introduce a new scope with an extra pair of {}
I often use it in conditionally compiled code, to avoid unused variable warnings:
#if DEBUG
{
struct node *tmp;
for (tmp=this; tmp; tmp= tmp->next) {
printf(stderr, "Node %u: %s\n", tmp->num, tmp->name);
}
}
#endif

This is standard C.
Section 6.8p1 of the C standard gives the following syntax for a statement:
statement:
labeled-statement
compound-statement
expression-statement
selection-statement
iteration-statement
jump-statement
Where a compound-statement is defined in section 6.8.2p1:
compound-statement:
{ block-item-list(opt) }
block-item-list:
block-item
block-item-list block-item
block-item:
declaration
statement
What this says is that anyplace that a statement can occur, a compound statement (i.e. a set of statements surrounded by {}) can occur.

Related

why do I need the curly braces here?

Consider this simple program:
fails.c:
#include <stdio.h>
int main(){
int i = 10;
if (i == 10)
int j = 11;
return 0;
}
That fails to compile (gcc fails.c), giving this error:
fails.c: In function ‘main’:
fails.c:7:3: error: expected expression before ‘int’
int j = 11;
^
But this one goes through just fine:
#include <stdio.h>
int main(){
int i = 10;
if (i == 10){
int j = 11;
}
return 0;
}
I figured that the work around, is to put those {} in. But I wish to know why this is required.
Why does it behave this way, when something like printf is acceptable?
#include <stdio.h>
int main(){
int i = 10;
if (i == 10)
printf("some text\n");
return 0;
}
This is because if must be followed by a statement:
C99/6.8.4
if ( expression ) statement
However, a declaration is not a statement:
C99/6.8
statement:
labeled-statement
compound-statement
expression-statement
selection-statement
iteration-statement
jump-statement
When put inside a {}, it is a compound-statement, thus ok.
There is a difference between declaration and statement.
int j = 11;
is a declaration. if statement shall be followed by a statement. Putting {} after if statement results in a compound statement. A compound statement can have no other statement in it or can have a declaration.
It seems you compile your ANSI C code with C89 standard. And, unlike his successor C99, it requires all variables to be declared at the beginning of the scope. So, having int j = 11; somewhere in-between other statements just contradicts that C89 rule. If you open a new scope just before that int j = 11;, it's back to OK.
Actual reason of such C89 limitation should be an attempt to simplify memory management for stack-allocable variables. For instance, compare it with Pascal language that requires all variables to be declared in the special var section before the code (so, it's even more strict that C89).

Confused about detecting the errors of this code in c programming language?

The code given below is an exercise that our teacher gave to prepare us for exams.
We are supposed to find the errors that occur in this code and fully explain them .
#define SIZE 10
int start (void a,int k) {
const int size=10;
char array[size];
char string[SIZE];
mycheck(3,4);
array[0]=string[0]='A';
printf("%c %c\n", array[0], string[0]);
myRec(7);
}
int mycheck(int a , int b) {
if (a==0 || b==0 ) {
return 0;
}
else {
return (a*b);
}
}
int myRec(int x) {
if(x==0)
return 0;
else
printf("%d,",x);
myRec(x--);
}
I have found these errors so far:
1.int start (void a,int k)
explanation: We can't have a variable of type void, because void is an incomplete type
2.const int size=10;
explanation:we can't use variable to define size of array
(problem is when I run it in dev-c++ it doesn't show an error so I'm not sure about this)
3.mycheck(3,4);
explanation: prototype of function mycheck() is not declared, so the function mycheck is not visible to the compiler while going through start() function
4.A friend told me that there is an error in function myRec because of this statement myRec(x--);
(I don't really get why is this an error and how you can I explain it?)
5.Main() function doesn't exist.
I'm not sure about this but if i run the code (in dev-c++) without main function I get a compilation error
I'm not sure if the errors that I pointed out are 100% right or if I missed an error or if I explained them correctly.
Please correct me if any of the above is wrong!
a friend told me that there is an error in function myRec cuz of this
statement myRec(x--);
It will lead to stackoverflow. Due to post-decrement, the actual argument passed to function myRec(), never decreases and therefore the condition:
if(x==0)
return 0;
will never become true. Regarding your rest of the errors, it depends on the compiler version being used:
For example C99, you are allowed to have variable size arrays like this:
const int size=10;
char array[size];
char string[SIZE];
but pre C99, you would have to use malloc or calloc. For your functions used without prototype, most compilers would generate a warning and not error and also due to no #include<stdio.h> statement, your printf would also lead to a warning.i Again, lot of these things are compiler dependent.
1.int start (void a,int k)
explanation: We can't have a variable of type void ,because void is an
incomplete type
Correct.
2.const int size=10;
explanation:we can't use variable to define size of array (problem is
when i run it in dev-c++ it doesnt show an error?so im not sure about
this!)
This is also correct, that char array[size];, where size is not a compile-time constant, is invalid in C89. However, in C99 and newer, this is actually valid and would create a variable-length array. It is possible that your Dev-C++ IDE is using GCC with the language set to C99 or newer, or has GNU C extensions enabled to enable this feature.
3.mycheck(3,4);
explanation: prototype of function mycheck() is not declared.So the
function mycheck is not visible to the compiler while going through
start() function
Correct. This can be fixed either by declaring the function's prototype before the start() function, or just moving the whole function to the top of the file. As noted by Toby Speight in the comments, in C89, this should not actually be a compiler error, since functions are implicitly declared when they are used before any actual declaration as int (), i.e. a function returning int with any arguments, which is compatible with the declarations of mycheck and myRec. It is however bad practice to rely on this, and implicit function declaration does not work in C99 or newer.
4.a friend told me that there is an error in function myRec cuz of this statement myRec(x--);
(I don't really get why is this an error and how you can explain it?)
This function is a recursive function. This means it calls itself within itself in order to achieve a kind of looping. However, this function as it is currently written would run forever and cause an infinite loop, and since it is a recursive function, and needs a new stack frame each time it is called, it will most likely end in a stack overflow.
The function is written with this statement:
if(x==0)
return 0;
This is intended to terminate the recursion as soon as x reaches 0. However, this never happens, because of this line of code here:
myRec(x--);
In C, postfix -- and ++ operators evaluate to their original value before the addition or subtraction:
int x = 5;
int y = x--;
/* x is now 4; y is now 5 */
However, using the prefix version of these operators will evaluate to their new value after adding / subtracting 1:
int x = 5;
int y = --x;
/* x is now 4; y is now 4 */
This means that on each recursion, the value of x never actually changes and so never reaches 0.
So this line of code should actually read:
myRec(--x);
Or even just this:
myRec(x - 1);
5.Main() function doesn't exist ...again im not sure about this but if i run the code (in dev-c++) without main function i get a compilation
error
This one could either be right or wrong. If the program is meant to run on its own, then yes, there should be a main function. It's possible that the function start here should actually be int main(void) or int main(int argc, char *argv[]). It is entirely valid however to compile a C file without a main, for example when making a library or one individual compilation unit in a bigger program where main is defined in another file.
Another problem with the program is that myRec is used before it is declared, just like your point 3 where mycheck is used before it is declared.
One more problem is that the functions start and mycheck are declared to return int, yet they both do not contain a return statement which returns an int value.
Other than that, assuming that this is the entire verbatim source of the program, the header stdio.h isn't included, yet the function printf is being used. Finally, there's the issue of inconsistent indentation. This may or may not be something you are being tested for, but it is good practice to indent function bodies, and indentation should be the same number of spaces / tab characters wherever it's used, e.g.:
int myRec(int x) {
if(x==0)
return 0;
else
printf("%d,",x);
myRec(x--);
}
1) Hello friend your Recursive function myRec() will go infinite because it
call itself with post detriment value as per C99 standard it will
first call it self then decrements but when it call itself again it have
to do the same task to calling self so it will never decrements and new
stack is created and none of any stack will clear that recursion so
stack will full and you will get segmentation fault because it will go
beyond stack size.
2) printf("%d,",x); it should be printf("%d",x); and you should include #include library.
I think your another mistake is you are calling your mycheck() and you
returning multiplication of two integer but you are not catch with any
value so that process got west.So while you are returning something you
must have to catch it otherwise no need to return it.
3) In this you Program main() function missing. Program execution starts
with main() so without it your code is nothing. if you want to execute
your code by your own function then you have to do some process but
here main() should be present.or instead of start() main() should
be present.
4) you can also allocate any char buffer like this int j; char array[j=20];
your code should be like this.
#include<stdio.h>
#define SIZE 10
int mycheck(int a , int b) {
if (a==0 || b==0 ) {
return 0;
}
else {
return (a*b);
}
}
int myRec(int x) {
if(x==0)
return 0;
else
printf("%d",x);
myRec(--x);
}
void main (int argc, char** argv) {
const int size=10;
char array[size];
char string[SIZE];
int catch = mycheck(3,4);
printf("return value:: %d\n",catch);
array[0]=string[0]='A';
printf("%c %c\n", array[0], string[0]);
myRec(7);
printf("\n");
}
Enjoy.............

initializing array of structure with array elements in it

#include <stdio.h>
int main()
{
typedef struct s
{
int a;
int b[5];
char c[2];
}st;
st vs[1];
vs[0] = {1,{1,2,3,4,5},{'c','d'}};
printf("%d:a\n",vs[1].a);
printf("%d:b[0]\t %d:b[4]\n",vs[0].b[0],vs[0].b[4]);
printf("%c:c[0]\t %c:c[1]\n",vs[0].c[0],vs[0].c[1]);
return 0;
}
why does this doesn't work?
on
gcc -o main *.c
I get this error
main.c: In function 'main':
main.c:15:12: error: expected expression before '{' token
vs[0] ={1,{1,2,3,4,5},{'c','d'}};
But if I have this:
#include <stdio.h>
int main()
{
typedef struct s
{
int a;
int b[5];
char c[2];
}st;
st vs[] = {
{1,{1,2,3,4,5},{'c','d'}}
};
printf("%d:a\n",vs[0].a);
printf("%d:b[0]\t %d:b[4]\n",vs[0].b[0],vs[0].b[4]);
printf("%c:c[0]\t %c:c[1]\n",vs[0].c[0],vs[0].c[1]);
return 0;
}
it works. What is the logic in this.
How can I make it work using st vs[1] method?
You can only do braced initialization when you declare a variable. So,
st vs[] = {
{1,{1,2,3,4,5},{'c','d'}}
};
is allowed. But
vs[0] = {1,{1,2,3,4,5},{'c','d'}};
is not. Because this is not a initialization but assignment.
However, you can use C99's compound literal, see C11, 6.5.2.5:
vs[0] = (struct s){1,{1,2,3,4,5},{'c','d'}};
Initialization is when you declare a variable and provide initial values for it as part of the declaration. For example this is legal:
st vs[1] = { {1,{1,2,3,4,5},{'c','d'}} };
Your code is actually attempting assignment. Assignment is when an existing variable has a value assigned to it. The reason your code doesn't work is that {1,{1,2,3,4,5},{'c','d'}} isn't a value.
In a statement (not a declaration), each expression must be readable by the compiler on its own merit, and a more complicated statement is made up of various expressions joined by operators. So the compiler doesn't know what to do with {1,{1,2,3,4,5},{'c','d'}} - at this stage it has no idea that that is supposed to be a st.
Since C99 there is a new language construct you can use here, called compound literal:
vs[0] = (const st){1,{1,2,3,4,5},{'c','d'}};
Note that this is not a cast operator being applied to some sort of braced expression; it is a single syntactic construct (Typename){ initializers } .
My use of const is a micro-optimization, it may help the compiler store the literal in a read-only block of the executable and allow constant folding.

mangling name in C

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.

What kind of c function is this?

I was reading "Compiler Design in C" book. In the basics section I found a c snippet for lexer something like this -
static int Lookahead = -1;
int match(token)
int token;
{
if(Lookahead == -1)
Lookahead = lex();
return token == Lookahead;
}
void advance(){
Lookahead = lex();
}
I got confuse about how this match function get compiled on gnu gcc. So I wrote a function that looks like
int a(token)
int token;
{
printf("Value of token is %d", token);
}
int main()
{
printf("Hello world!\n");
a(1);
return 0;
}
And I am getting following output-
Hello world!
Value of token is 1
But I dont getting the reason behind that function declaration. What the benefit of declaring function this way? And how the value of token being 1? Why its not a compile error? Is it some kind of function declaration in C?
Thanks for checking my question. Any kind of help will be great.
Its an old and deprecated K&R style of function declaration.
int match(token)
int token;
{
// Function body
}
is equivalent to
int match(int token)
{
// Function body
}
except that in former, compiler would not check that the function is called with the right number of arguments nor will it check the types of arguments. It rely on default argument promotions.
C89 and C99 support this style too.
This is the original way that C functions used to be declared when Kernighan and Ritchie first developed the C programming language. It is referred to as 'K&R C'
C went through a standardisation process and this form of function declaration was changed to the one that you are used to.
On the page http://en.wikipedia.org/wiki/The_C_Programming_Language the first edition of the book would have had the old style function declarations, I think it was dropped in the second edition.
Function definitions in the original K&R C were simpler. In your example, the type declaration for function parameter token is actually redundant. The code could be simplified this way:
static int Lookahead = -1;
int match(token) {
if (Lookahead == -1)
Lookahead = lex();
return token == Lookahead;
}
void advance(){
Lookahead = lex();
}
Indeed the function return type and variable types also defaulted to int, void was not yet invented, the return statement was optional... leading to further simplification:
static Lookahead=-1;
match(token){
if(Lookahead==-1) Lookahead=lex();
return token==Lookahead;
}
advance(){Lookahead=lex();}
Such primitive style was more compact, but was quite error prone and is no longer supported by modern conforming compilers. The function definition syntax in your example is still supported, but considered obsolete and likely to disappear at some point.

Resources