Is this fragment valid? - c

char name[] = {};
gets(name);
Is this fragment valid if I want to take a name of unknown value length and store it on name array ?
I wanted to take a name of unknown length input as a string.

char name[] = {}; is invalid C, an initializer list must contain at least 1 item.
gets(name); is invalid C, the gets function was finally removed from the C language in year 2011, after it was flagged as obsolescent in the 1990s. Sources of learning teaching you to use gets should be retired.
There is a gcc non-standard extension allowing empty {} but don't write non-standard C just for the heck of it.
There is a gcc non-standard extension allowing the use of gets by including stdio.h or by compiling as -std=c90/-std=c99, but don't use that function anywhere, since it was intrinsically broken by design from day 1. Use fgets instead.
Even with these extensions present you didn't allocate any memory for name so the code is broken even then.
I strongly recommend to start using these compiler options: What compiler options are recommended for beginners learning C?

Related

Assigning a "string" to a varible previously declared as "int"

I am new to programming and on learning dynamic typing in python, it arisess a doubt in "static typing". I tried out this code (assigning a string to an integer variable which was previously declared) and printing the variable as printf(var_name) and its gives output; can anyone explain this concept?
#include<stdio.h>
#include<conio.h>
void main()
{
int i = 20 ;
i = "hello";
printf(i);
}
Besides your question might be a duplicate, let me append something missing of the read worthy answer https://stackoverflow.com/a/430414/3537677
C is strongly/statically typed but weakly checked
This is one of the biggest core language features which sets C apart from other languages like C++. (Which people are used to mistake a simply "C with classes"
Meaning although C has a strong type system in the context of needing and using it for knowing sizes of types at compile time, the C languages does not have a type system in order to check them for misuse. So compilers are neither mandated to check it nor are they allowed to error your code, because its legal C code. Modern compilers will issue a warning dough.
C compilers are only ensuring "their type system" for the mentioned size management. Meaning, if you just type int i = 42; this variable has so called automatic storage duration or what many people are calling more or less correctly "the stack". It means the compiler will take care of getting space for the variable and cleaning it up. If it can not know the size of it, but needs it then it will indeed generate an error. But this can be circumvented by doing things at run-time and using of types without any type whats so ever, i.e. pointers and void* aka void-pointers.
Regarding your code
Your code seems to be an old, non standard C compiler judging by the #include<conio.h> and void returning main. With a few modifications one can compile your code, but by calling printf with an illegal format string, you are causing so called undefined behaviour (UB), meaning it might work on your machine, but crashes on mine.

Is there a function to count number of parameters for a printf format string?

Say, if I do the following:
const char *strFmt = "Value=%d, str=%s, v=%I64d. Is 100%% true";
printf(strFmt, 1, "name", -1);
Is there a function that simply returns how many parameters are needed for strFmt without filling them in?
The usual reason for wanting the number of required parameters is to check one's code. C runtime libraries do this as a side-effect of the printf function. Source for those (as well as for similar printf-like functions such as StrAllocVsprintf in Lynx) can be found easily enough.
Because printf is a varargs function, there is no predefined prototype which tells the "right" number of parameters.
If there are too few parameters, bad things can happen ("undefined behavior"), while extra ones may be ignored. Most modern compilers provide some help, in the form of compile-time warnings.
There is no standard function to count the number of required parameters. The question has been asked before, e.g.,
Linux script that counts number of printf parameters for each occurrence
Passing too many arguments to printf
For whatever historical reason, the function also has (apparently) not been provided by any compiler suite. In most cases, this is because printf formats are usually checked by the compiler (or static analysis tools such as lint). Not all compilers do these checks. A few can be told using that some functions aside from printf and its standard relatives are "printf-like". Visual Studio lacks that feature, but can do some printf-checking (not a lot according to Is there any way to make visual C++ (9.0) generate warnings about printf format strings not matching type of printf's args?).
A string constant is not going to be associated by the compiler with the printf function. You could make it a #define and reuse the value in an actual printf function to get whatever checking the compiler can do.
For instance
#define strFmt "Value=%d, str=%s, v=%I64d. Is 100%% true"
printf(strFmt, 1, "name", -1);
The problem itself is portable: if your program also is portable, you can check it with other tools than the Visual Studio compiler.

Need help to understand the syntax in xv6 kernel

I am reading files of xv6 kernel and I cannot understand what the following means:
static int (*syscalls[])(void) = {
[SYS_fork] sys_fork,
[SYS_exit] sys_exit,
[SYS_wait] sys_wait,
[SYS_pipe] sys_pipe,
...
}
Can someone explain this to me? Especially what square brackets (e.g [SYS_fork]) mean.
Thank you
That code is making an array of function pointers, using an old alternative GNU extension for designated initialization.
Designated initializations is a feature that was added to C in C99 that lets you specify which array index to assign a specific value for arrays, so they need not be in order. The same feature exists for struct initializations where you can specify the specific field to assign a given value to.
The C99 syntax for array designated initializations is [index] = value. This code in particular though is using an older alternative syntax from GCC, which as per this document has been obsolete since GCC 2.5, in which there is no equals sign used.
In syscall.c the indices are specified using macros defined in syscall.h, the first of which is defined to 1 in syscall.h, et.c.
This is most likely a non-standard way of initializing an array of function pointers. The identifiers SYS_fork etc. are very likely macros or enum constants specifying the element index.
Another possibility is that this is not a C file, but is turned into a syntactically valid C file using some filtering tool prior to compilation.

How does defining function variables before { and after function declaration work? [duplicate]

I generated a hash function with gperf couple of days ago. What I saw for the hash function was alien to me. It was something like this (I don't remember the exact syntax) :
unsigned int
hash(str, size)
register char* str;
register unsigned int size;
{
//Definition
}
Now, when I tried to compile with a C++ compiler (g++) it threw errors at me for not having str and size declared. But this compiled on the C compiler (gcc). So, questions:
I thought C++ was a superset of C. If its so, this should compile with a C++ compiler as well right?
How does the C compiler understand the definition? str and size are undeclared when they first appear.
What is the purpose of declaring str and size after function signature but before function body rather than following the normal approach of doing it in either of the two places?
How do I get this function to compile on g++ so I can use it in my C++ code? Or should I try generating C++ code from gperf? Is that possible?
1. C++ is not a superset, although this is not standard C either.
2/3. This is a K&R function declaration. See What are the major differences between ANSI C and K&R C?
.
4. gperf does in fact have an option, -L, to specify the language. You can just use -L C++ to use C++.
The Old C syntax for the declaration of a function's formal arguments is still supported by some compilers.
For example
int func (x)
int x
{
}
is old style (K&R style) syntax for defining a function.
I thought C++ was a superset of C. If its so, this should compile with a C++ compiler as well right?
Nopes! C++ is not a superset of C. This style(syntax) of function declaration/definition was once a part of C but has never been a part of C++. So it shouldn't compile with a C++ compiler.
This appears to be "old-school" C code. Declaring the types of the parameters outside of the parentheses but before the open curl-brace of the code block is a relic of the early days of C programming (I'm not sure why but I guess it has something to do with variable management on the stack and/or compiler design).
To answer your questions:
Calling C++ a "superset" of C is somewhat a misnomer. While they share basic syntax features, and you can even make all sorts of C library calls from C++, they have striking differences with respect to type safety, warnings vs. errors (C is more permissible), and compiler/preprocessor options.
Most contemporary C compilers understand legacy code (such as this appears to be). The C compiler holds the function parameter names sort of like "placeholders" until their type can be declared immediately following the function header name.
No real "purpose" other than again, this appears to be ancient code, and the style back in the day was like this. The "normal" approach is IMO the better, more intuitive way.
My suggestion:
unsigned int hash(register char *str, register unsigned int size)
{
// Definition
}
A word of advice: Consider abandoning the register keyword - this was used in old C programs as a way of specifying that the variable would be stored in a memory register (for speed/efficiency), but nowadays compilers are better at optimizing away this need. I believe that modern compilers ignore it. Also, you cannot use the & (address of) operator in C/C++ on a register variable.

Getting Variable dynamic in c

I have one requirement in C.
char abc[]="hello";
char hello[]="world";
Using abc whether we can get the hello variable's value in C.
I know it is possible in some of the languages like Perl, Php, Bash,.,
Is it possible in C?
Yes you are right , this is possible in some other language but not in C ,
since abc is a container which resides in a location (for ex: 1000) and hello is one more
container which resides in another location ( for ex : 2000 ) , so we have no contact between
these two arrays ,
we cannot make a value ( strings ) to point some other value.
so finally THIS IS NOT AT ALL POSSIBLE.
No, this is not possible in C without providing a string lookup table of some sort that could link variables with their names.
It's impossible in C, unlike in more dynamic languages like Perl or Python. However, it's important to keep in mind that even in those languages this isn't recommended. I haven't seen a snippet of code putting this to a good use yet. The eval methods available in dynamic languages are used sparingly, and not for dynamically grabbing variable names.
As soon as the C compiler has figured out where to store the underlying pointers, it forgets about the name you gave it. The dynamic languages solve it with a data structure like a hash map which allows you to store the pointers (value) under a key (the name).
Another option is to read in the debug information. This is only available if you compile your code with -g (gcc) or some other, compiler specific option. Note that the debug format is not standardized, so you'll need to figure out what your compiler uses and how to work with it.
It is not possible in C. It can be done in java by reflection in some cases.
POSIX has several functions that allows you to do it, assuming variable hello is global and isn't static:
void *handle = dlopen(NULL, RTLD_NOW);
// error handling omitted
printf("%s variable contains value %s", abc, (char *)dlsym(handle, abc));
dlsym() return value is casted to char * to suppress warning when using compilers that check format string for printf-alike functions.
And you need to make sure you've specified correct compiler options, e.g. -rdynamic -ldl in case of GCC.

Resources