Is this a valid C program? - c

I wrote a program, where the size of an array is taken as an input from user.
#include <stdio.h>
main()
{
int x;
scanf("%d", &x);
int y[x];
/* some stuff */
}
This program failed to compile on my school's compiler Turbo C (an antique compiler).
But when I tried this on my PC with GNU CC, it compiled successfully.
So my question is, is this a valid C program? Can I set the size of the array using a user's input?

It is a valid C program now, but it wasn't 15 years ago.
Either way, it's a buggy C program because x is used without any knowledge of how large it might be. The user can input a malicious value for x and cause the program to crash or worse.

C99 gives C programmers the ability to use variable length arrays,which are arrays whose sizes are not known until run time. --C:A Reference Manual

c90 does not support variable length arrays you can see this using this command line:
gcc -std=c90 -pedantic code.c
you will see an error message like this:
warning: ISO C90 forbids variable length array ‘y’ [-Wvla]
but c99 this is perfectly valid:
gcc -std=c99 -pedantic code.c

Instead of asking whether this is strictly valid C code, it may be better to ask whether it is good C code. Although it is valid, as you have seen, a number of compilers do not support variable length arrays.
Variable length arrays are not supported by a number of modern compilers. These include Microsoft Visual Studio and some versions of the IBM XL compilers. As you have found, variable length arrays are not entirely portable. That's fine if the code will only be used on systems that support the feature but not if it has to be run on other systems. Instead, it may be better to allocate the array with constant size using a reasonable limit or use a malloc and free to create the array in portable manner.

Related

Is $ an operator in C if yes then why?

I got this confusion when I was working on infix to prefix conversion using C
Infix Expression:A-B+(N$N)(O+P)+Q/R^ST+Z
where I found $ being used as an operator.
So to clear my doubt I made a program performing a$b operation in C to see if it is yielding results like other operators but got to see no answer.
The output further increased my doubt regarding the $ operator and its use in C.
If a=5,b=6 then if we do a+b and print the sum we get 11. In the case of $ if we are considering it as an operator and doing a$b then I am not getting any result. So I was confused that whether $ is an operator or not in the case of C
Some compilers (including GCC) accept, as an extension to the C language, a $ inside an identifier. You may also need support from your linker and assembler.
But standard C usually disallow that. Read e.g. Modern C to learn more, and also the n2176 draft standard. Check also this C reference website (it seems that $ are permitted in recent C standards).
IIRC, on VAX computers under VMS, you did have a lot of system identifiers with a $.
I guess you could improve some open source C compiler (not only GCC, but also Clang, tinycc, nwcc...) to accept $ as some operator.
My recommendation would be to not use $ in your identifiers, and to take inspiration from existing open source software (e.g. GTK).
For example the following /tmp/dollar.c file
#include <stdio.h>
int main(int argc, char**argv)
{
int doll$ar = 2;
printf("from %s doll$ar is %d and argc is %d\n",
argv[0], doll$ar, argc);
}
using GCC 10 on Linux/x86-64 in December 2020 as gcc -Wall -Wextra /tmp/dollar.c -o /tmp/dollar compiles without warnings. When I run /tmp/dollar the output is:
from /tmp/dollar doll$ar is 2 and argc is 1
Few open source software (look into the source code of GNU make or GNU bash) are using $ in identifiers.
PS. I believe that future standards might allow UTF-8 letters in identifiers, but you need to check with your ISO representative.

Compilation error of Variable Length Array with GCC

How to make a compilation successful for a program with a variable length array?(currently, Showing error : Variable sized array). I am using gcc in linux. How to make compiler compatible to c99 standard ? PLease help me in this. THanks in advance.
How to make compiler compatible to c99 standard?
By default, the compiler defaults to the most compatible version of C version is installed. Do define the compilation version explicitly, compile the program with the following command-line:
$ gcc -std=c99 -o my_program my_program.c
By defining the -std=c99, the compiler will be using C99 standard.
Edit: If you're still getting the warning and not the error, then you need to provide your code to know what exactly is wrong.
"How to make a compilation successful for a program with a variable length array? (currently, Showing error : Variable sized array)."
Usually it isn't an error to compile a code with a VLA unless you compile with -Werror flag.
The diagnostic you get is high-probably "only" a warning that you use a VLA inside of it, which is risky.
Thus, the compiler informs you about that.
So, you indeed can compile a program with VLAs without any error.
If you got errors they must belong to anything else. We can't find those out since you showed no specific code.
Take a look at this question of mine, not so long ago (even if it is for Clang, it covers the same topic as the answers suggest that a compiler is free to complain about whatever it likes):
Why does clang complain about using variable-length arrays with '-std=c99' flag?
All useful information you can find there.
VLAs are not portable. Try to use alternatives, for example dynamically allocated arrays by using malloc().
Related:
malloced array VS. variable-length-array
Is there any overhead for using variable-length arrays?
Is it a good idea to use C99 VLA compared to malloc/free?
"How to make compiler compatible to (the) C99 standard?"
As Rohan in his answer already said, you can use the -std-c99 flag at the invocation of gcc for that. But it probably won't solve your problem to do so.

What is this value? [duplicate]

This question already has answers here:
How printf("%d","<string>") work in C?
(2 answers)
Closed 4 years ago.
printf("%d", "10+10");
then I get "17661648" and similar thing in too
printf("%d", "Hello");
What is this value?
sum of "1,0,+,1,0" "H,e,l,l,o" as ASCII code in decimal number? or just a garbage value?
According the the C11 standard n1570 (see its §7.21.6.1) you've got undefined behavior (UB), which is also documented here or in printf(3). So be very scared, since arbitrarily bad things could happen. So take the habit of reading the documentation of every function that you are using.
If you ask your compiler to disassemble the generated form of your program (e.g. by compiling with gcc -S -O -fverbose-asm if you use GCC, on Linux/x86-64) you'll discover that the address of the string literal "10+10" is passed (on 64 bits) and then truncated (inside printf, because of the %d) to an int. So the 17661648 could correspond to the lowest 32 bits of that address.
Details are of course implementation specific (and could vary from one run to the next one because of ASLR, depends upon the compiler and the ABI and the target system). To actually understand and explain the behavior requires diving into many details (your particular computer, your particular compiler and optimization flags, your particular operating system, the compiler generated assembler & machine code, your particular C standard library, etc....) and you don't want to do that (because it could take years).
You should take several hours to read more about UB. It is an essential notion to understand when programming in C, and you should avoid it.
Any good compiler would have warned you, and then you should improve your code to get no warnings. If using GCC, be sure to compile with gcc -Wall -Wextra -g to get all warnings and debug info. Then use the gdb debugger to understand the actual behavior of your program on your system. In all cases, be sure to configure your C compiler to enable all warnings and debug info, and learn to use your debugger. Read How To Debug Small Programs.
Someting like this should work:
printf("Hello");
total = 20;
printf("10+10 = %d", total);

Which compiler should I trust?

This is going to be some what of a newbie question but I was trying to work on a small exercise in the C Language (not C++) and I was running into some issues.
Say I wanted to use an array within a method whose size depended on one of the arguments:
void someFunc(int arSize)
{
char charArray[arSize];
// DO STUFF
...
}
When I try to compile this as a .c file within Visual Studio 2013 I get an error saying that a non-constant array size is not allowed. However the same code works within CodeBlocks under a GNU Compiler. Which should I trust? Is this normal for compilers to behave so differently? I always thought that if you're doing something that a compiler doesn't like you shouldn't be doing it in the first place because it's not a standard.
Any input is useful! I come from a Background in Python and I am trying to get more heavily involved in programming with Data-Structures and Algorithms.
My platform is Windows as you can probably tell. Please let me know if this question needs more information before it can be answered.
Variable length arrays(VLA) are a C99 feature and Visual Studio until recently did not support C99 and I am not sure if it currently supports VLA in the lastest version. gcc on the other hand does support C99 although not fully. gcc supports VLA as an extension outside of C99 mode, even in C++.
From the draft C99 standard section 6.7.5.2 Array declarators paragraph 4:
[...] If the size is an integer constant expression and the element type has a known constant size, the array type is not a variable length array type; otherwise, the array type is a variable length array type.
You should trust the compilers that you're using and that you want to support.
On that particular issue: non-constant array sizes are valid in C99, which isn't fully supported by either gcc or by MSVC (Microsoft's C/C++ compiler). gcc, however, has this feature from the standard implemented even outside of C99 mode, while MSVC hasn't.
It depends upon the particular standard your C compiler is following.
The feature you want is called variable length array (VLA) and was introduced into the C99 standard.
Maybe your Visual Studio is supporting some earlier version of the standard. Perhaps you might configure it to support a later version.
Notice that using VLA with a huge size could be a bad habit: VLA are generally stack allocated, and a call frame stack should usually have a small size (a few kilobytes at most on current processors), especially for kernel code or for recursive or multithreaded functions. You may want to heap-allocate (e.g. with calloc) your array if it is has more than a thousand words. Then you'll need to free it later.
This is a GCC extension acting on you.

MinGW compiler doesn't need function declarations?

I have these two files:
// first.c
int main(void) {
putint(3);
}
and
// second.c
#include <stdio.h>
void putint(int n) {
printf("%d",n);
getchar();
}
When I run gcc 4.6.1 under Win XP:
gcc first.c second.c -o program.exe
It has no problem and writes 3 to stdout. It doesn't need putint declaration in first.c. How is this possible? Is this standard behavior?
I have tested this on MSVC 2008 Express and it runs only with the declaration as expected.
// first.c
void putint(int);
int main(void) {
putint(3);
}
Solved, thanks for hints, these options helped to show the warning:
-Wimplicit
-std=c99 (MinGW 4.6 still uses gnu90 by default)
This is a legacy "feature" of C that should not be used as of several decades ago. You should use a compiler with settings that will warn you if you do something like this. Gcc has several switches that you should specify when using it & one of them will give you a warning for this.
Edit: I haven't been using gcc myself, but switches that you should check out are -pedantic, -Wall, -Wextra, and -std.
The compiler that is accepting this is assuming, per the old language definition, that since you didn't see fit to tell it otherwise, the function a) returns an int value and b) since you pass it an int (or if you passed it something that could be promoted to an int) the function expects that argument to be an int.
As #veer correctly points out, this should generally work in your particular case. In other cases, however, differences between the implicit assumptions for a function without a prototype and the function's actual signature would make things go boom.
This isn't just for MinGW, but all standard versions of gcc. As noted, this is legal in C89; gcc defaults to 'gnu89' (not 99), which also accepts the code without warning. If you switch to c99 or gnu99 (or later, such as c11) you'll get a warning by default, but it will still compile.
As is noted by others, this is standard behavior for C conforming compilers. Naming your files .c partially puts it in C mode. It'll have fun things like "built-in functions" (printf() etc.) and all sorts of legacy C things.
I'd like to add to what others have said that I experienced recently, though. MS expressly dropped support for C past C90, and their C90 support is poor to say the least. I'm not entirely sure standard ANSI C90 codebases would compile under newer VS's, because it is basically the C++ compiler with lots of stuff disabled (whereas GCC actually has a C compiler). They did this in order to promote C++. If you want to use real C, you can't really do it in MS Visual Studio, any edition, unless you want to be declaring all your variables at the start of functions, etc.

Resources