So I understand the use of typecasting. Making a type of variable act as another. But everytime I attempt to do so it prints a diamond lol?
#include <stdio.h>
#include <strings.h>
#include <windows.h>
void loginscreen(void)
{
printf("\nWelcome to the login screen...\n");
int num = 4;
printf("%c", (char)num);
getchar();
}
Also can I get an explanation of malloc and why and how it uses typecasting.
You are casting the number 4 to the ASCII character 4, which happens to be EOT (End of Transmission). This is a special character that signals the end of the input. In Unix-like systems it can be generated by pressing Ctrl+D (Ctrl+Z in Windows). As this is a non-printable character, your terminal is probably displaying it as '�', the replacement character used to replace an unknown or unrepresentable character.
Addressing your other question, malloc() basically asks the system to give you a chunk of memory. There are plenty of wonderful resources on the web where you can find very good explanations.
Casting (not "typecasting" doesn't make a type of variable act as another; it converts a value of one type to another type (or perhaps to the same type).
(Pointer conversions can be used to reinterpret an object as an object of a different type. Your code doesn't do that.)
Some conversions are implicit; others are explicit. A cast is an operator consisting of a parenthesized type name; it specifies an explicit conversion. (There's no such thing as an implicit cast.)
In your example:
printf("%c", (char)num);\
the value of num (which is of type int) is converted to type char. It's then immediately converted (promoted) back to type int, because that's the behavior when something of a type narrower than int is passed as an argument to a variadic function like printf. It would behave exactly the same way without the cast:
printf("%c\n", num);
It prints the character whose value is 4, which happens to be a non-printable control character.
You asked about malloc, but since there's no call to malloc in your code, that's (a) a separate question, and (b) it's rather vague. If you have a more specific question about malloc, you can post it separately. But first, I suggest reading section 7 of the comp.lang.c FAQ, which discusses memory allocation. (In particular, you should not cast the result of malloc; it's unnecessary and can mask errors in some cases.)
Related
I'm on programming project 4 from chapter 19 of C programming, A Modern Approach. My code works but I get this warning trying to pass a function returning a void * parameter to printf with conversion specifier %s.
format %s expects argument of type char *, but argument 2 has type void * [-Wformat=]
I can easily get rid of the warning by casting the return type of the function to char *, like
printf("%s\n", (char *) function(param));
but I just want to know why this necessary since type void * is casted to another pointer type automatically.
Compiler is very right to complain in this case.
As per your logic itself, the function returning void * could return a structure pointer casted to void *, but then, %s won't be able to print that, isn't it?
So, if you know what you're doing, you can cast the result, for this case.
Also, as others pointed out, maybe it's worthy to mention that, this warning has nothing to do with the standard specification, as in the standards, there is no restriction of the type of the arguments. (Borrowing Mr. #WhozCraig's words) This warning is basically due to an additional layer of type-checking entirely performed by compiler on it's own, enabled by -Wformat flag in gcc .
As far as the pure language is concerned (not the standard library and its expectations, the actual formal language) you can push anything you want on that argument list (including something utterly incoherent in relating to the requirements of a %s format specifier of some library routine). Of course, unless whatever you pushed ultimately is, in fact, the address of a nullchar terminated sequence of char, printf itself will trapes into undefined behavior at your behest.
The warning you're receiving is based on an additional layer of api-checking within the compiler, not some violation of the language itself. That api checking is matching format specs with types of presented arguments for frequently-used standard library apis such as printf, scanf, etc. Could the author of that warning-check been a little more forgiving and ignore void* arguments for specs expecting pointer-types? Certainly, but the point of the check-feature would dwindle pretty rapidly were that the case. Consider this:
int a = 0;
void *b = &a;
printf("%s\n", b);
If that api-check feature is going to be worth any salt at all it had better bark about that mismatched type, because as far as the language itself is concerned, there is nothing wrong with this code. And that has nothing to do with what evil I just requested it do. As far as the language is concerned, printf is simply this:
int printf(char *format ...);
And the call I setup certainly fulfills that (bad for me, and thankfully, the api-checks of my modern compiler will let me know soon enough there may be a problem).
A pointer is a variable which points to a single memory location.
The number of bytes pointed by the pointer depends on the type of the pointer. So if it is int* then it is interpreted as 4 bytes,if it is a char* it is interpreted as 1 byte.
A void* has no type. So the compiler cant dereference this pointer. So in order for the compiler to understand the memory to be dereferenced we need typecasting here.
The printf function is declared as something like this:
int printf(char *format ...);
Here ... denotes any additional arguments the caller supplied (that is, your string you wanted to print). When printf examines these additional parameters, it uses some low-level code, which has no type safety.
This code cannot determine that the parameter has type void*, and cast it to char* automatically. Instead, if the binary representation of void* and char* is the same, the parameter can be extracted from the ... part without regard to its actual type. If the representation is different, the low-level code will try to print an incorrect value (and probably crash).
Representation of void* and char* is the same for all platforms that I know of, so it's probably safe (if you trust me, that is - please don't!). However, if you compile with gcc -Wall, as some people recommend, all warnings are upgraded to errors, so you should do the casting, as the compiler indicates.
As you can see from the code snippet below, I have declared one char variable and one int variable. When the code gets compiled, it must identify the data types of variables str and i.
Why do I need to tell again during scanning my variable that it's a string or integer variable by specifying %s or %d to scanf? Isn't the compiler mature enough to identify that when I declared my variables?
#include <stdio.h>
int main ()
{
char str [80];
int i;
printf ("Enter your family name: ");
scanf ("%s",str);
printf ("Enter your age: ");
scanf ("%d",&i);
return 0;
}
Because there's no portable way for a variable argument functions like scanf and printf to know the types of the variable arguments, not even how many arguments are passed.
See C FAQ: How can I discover how many arguments a function was actually called with?
This is the reason there must be at least one fixed argument to determine the number, and maybe the types, of the variable arguments. And this argument (the standard calls it parmN, see C11(ISO/IEC 9899:201x) §7.16 Variable arguments ) plays this special role, and will be passed to the macro va_start. In another word, you can't have a function with a prototype like this in standard C:
void foo(...);
The reason why the compiler can not provide the necessary information is simply, because the compiler is not involved here. The prototype of the functions doesn't specify the types, because these functions have variable types. So the actual data types are not determined at compile time, but at runtime.
The function then takes one argument from the stack, after the other. These values don't have any type information associated with it, so the only way, the function knows how to interpret the data is, by using the caller provided information, which is the format string.
The functions themselves don't know which data types are passed in, nor do they know the number of arguments passed, so there is no way that printf can decide this on it's own.
In C++ you can use operator overloading, but this is an entire different mechanism. Because here the compiler chooses the appropriate function based on the datatypes and available overloaded function.
To illustrate this, printf, when compiled looks like this:
push value1
...
push valueN
push format_string
call _printf
And the prototype of printf is this:
int printf ( const char * format, ... );
So there is no type information carried over, except what is provided in the format string.
printf is not an intrinsic function. It's not part of the C language per se. All the compiler does is generate code to call printf, passing whatever parameters. Now, because C does not provide reflection as a mechanism to figure out type information at run time, the programmer has to explicitly provide the needed info.
Compiler may be smart, but functions printf or scanf are stupid - they do not know what is the type of the parameter do you pass for every call. This is why you need to pass %s or %d every time.
The first parameter is a format string. If you're printing a decimal number, it may look like:
"%d" (decimal number)
"%5d" (decimal number padded to width 5 with spaces)
"%05d" (decimal number padded to width 5 with zeros)
"%+d" (decimal number, always with a sign)
"Value: %d\n" (some content before/after the number)
etc, see for example Format placeholders on Wikipedia to have an idea what format strings can contain.
Also there can be more than one parameter here:
"%s - %d" (a string, then some content, then a number)
Isn't the compiler matured enough to identify that when I declared my
variable?
No.
You're using a language specified decades ago. Don't expect modern design aesthetics from C, because it's not a modern language. Modern languages will tend to trade a small amount of efficiency in compilation, interpretation or execution for an improvement in usability or clarity. C hails from a time when computer processing time was expensive and in highly limited supply, and its design reflects this.
It's also why C and C++ remain the languages of choice when you really, really care about being fast, efficient or close to the metal.
scanf as prototype int scanf ( const char * format, ... ); says stores given data according to the parameter format into the locations pointed by the additional arguments.
It is not related with compiler, it is all about syntax defined for scanf.Parameter format is required to let scanf know about the size to reserve for data to be entered.
GCC (and possibly other C compilers) keep track of argument types, at least in some situations. But the language is not designed that way.
The printf function is an ordinary function which accepts variable arguments. Variable arguments require some kind of run-time-type identification scheme, but in the C language, values do not carry any run time type information. (Of course, C programmers can create run-time-typing schemes using structures or bit manipulation tricks, but these are not integrated into the language.)
When we develop a function like this:
void foo(int a, int b, ...);
we can pass "any" number of additional arguments after the second one, and it is up to us to determine how many there are and what are their types using some sort of protocol which is outside of the function passing mechanism.
For instance if we call this function like this:
foo(1, 2, 3.0);
foo(1, 2, "abc");
there is no way that the callee can distinguish the cases. There are just some bits in a parameter passing area, and we have no idea whether they represent a pointer to character data or a floating point number.
The possibilities for communicating this type of information are numerous. For example in POSIX, the exec family of functions use variable arguments which have all the same type, char *, and a null pointer is used to indicate the end of the list:
#include <stdarg.h>
void my_exec(char *progname, ...)
{
va_list variable_args;
va_start (variable_args, progname);
for (;;) {
char *arg = va_arg(variable_args, char *);
if (arg == 0)
break;
/* process arg */
}
va_end(variable_args);
/*...*/
}
If the caller forgets to pass a null pointer terminator, the behavior will be undefined because the function will keep invoking va_arg after it has consumed all of the arguments. Our my_exec function has to be called like this:
my_exec("foo", "bar", "xyzzy", (char *) 0);
The cast on the 0 is required because there is no context for it to be interpreted as a null pointer constant: the compiler has no idea that the intended type for that argument is a pointer type. Furthermore (void *) 0 isn't correct because it will simply be passed as the void * type and not char *, though the two are almost certainly compatible at the binary level so it will work in practice. A common mistake with that type of exec function is this:
my_exec("foo", "bar", "xyzzy", NULL);
where the compiler's NULL happens to be defined as 0 without any (void *) cast.
Another possible scheme is to require the caller to pass down a number which indicates how many arguments there are. Of course, that number could be incorrect.
In the case of printf, the format string describes the argument list. The function parses it and extracts the arguments accordingly.
As mentioned at the outset, some compilers, notably the GNU C Compiler, can parse format strings at compile time and perform static type checking against the number and types of arguments.
However, note that a format string can be other than a literal, and may be computed at run
time, which is impervious to such type checking schemes. Fictitious example:
char *fmt_string = message_lookup(current_language, message_code);
/* no type checking from gcc in this case: fmt_string could have
four conversion specifiers, or ones not matching the types of
arg1, arg2, arg3, without generating any diagnostic. */
snprintf(buffer, sizeof buffer, fmt_string, arg1, arg2, arg3);
It is because this is the only way to tell the functions (like printf scanf) that which type of value you are passing. for example-
int main()
{
int i=22;
printf("%c",i);
return 0;
}
this code will print character not integer 22. because you have told the printf function to treat the variable as char.
printf and scanf are I/O functions that are designed and defined in a way to receive a control string and a list of arguments.
The functions does not know the type of parameter passed to it , and Compiler also cant pass this information to it.
Because in the printf you're not specifying data type, you're specifying data format. This is an important distinction in any language, and it's doubly important in C.
When you scan in a string with with %s, you're not saying "parse a string input for my string variable." You can't say that in C because C doesn't have a string type. The closest thing C has to a string variable is a fixed-size character array that happens to contain a characters representing a string, with the end of string indicated by a null character. So what you're really saying is "here's an array to hold the string, I promise it's big enough for the string input I want you to parse."
Primitive? Of course. C was invented over 40 years ago, when a typical machine had at most 64K of RAM. In such an environment, conserving RAM had a higher priority than sophisticated string manipulation.
Still, the %s scanner persists in more advanced programming environments, where there are string data types. Because it's about scanning, not typing.
I'm trying to create an array of structs, of which the array size is defined by the user in the program. eg. p[0], p[1], p[2].....
typedef struct
{
int score;
}player;
void main()
{
int numPlayers;
printf ("\nEnter number of players (1 - 4)\n");
scanf ("%d", &numPlayers);
}
I've tried doing it with both
player p[numPlayers];
and
player *p=malloc(numPlayers*sizeof(player));
but both won't compile.
Can anyone see what's going wrong here?
Edit: I'm using VS2010.
I'm getting "expression must have a constant value" for the first one, and "a value of type "void*" cannot be used to initialise an entity of type "player*" for the second one.
The player p[numPlayers]; approach calls for a "variable length array". This is a feature which appeared in the GNU C dialect many years ago, and was adopted into the C language in 1999. To get that to compile you need a compiler which recognizes this as an extension, or a C99 compiler. Variable Length Arrays have a downside: they are usually implemented by allocating the memory on the stack. There is no way to detect whether or not there is enough memory.
The malloc calling syntax you have is fine:
player *p=malloc(numPlayers*sizeof(player));
However, if you want to write this anywhere in your function, you need to be using a C99 compiler, or a compiler that accepts inter-mingled statements and declarations (like GNU C which has had that as an extension for years before C99 and accepts it by default. In C90, you have to declare the pointer in the block of declarations at the top of the function (or braced statement): player *p = NULL;. Then later, after the number of players is known, assign to it p = malloc ....
You should post the actual program that doesn't compile. Without that we are only guessing!
Moreover, you have some problems.
Firstly, if you want to call malloc, you should include the header <stdlib.h> where malloc is declared.
Secondly, main should return type int not void.
Also, check the return value of scanf. The scanf function is bad for interactive input. For instance if the user hits Enter, scanf keeps waiting for input, looking for those numeric characters, which is unfriendly. scanf also has no error checking in %d. If you enter a number that doesn't fit into the type int the behavior is simply undefined. This type of input handling is only suitable for quick-and-dirty "throwaway" programs written for the author's own use.
One possibility would be that you've forgotten to #include <stdlib.h>. Without a prototype for it, the compiler will assume that malloc returns an int, which won't convert to a pointer without a cast (but don't use a cast -- include the proper header so the compiler knows the return type instead).
Edit: It's unrelated, but FWIW, main should return int, not void.
I have a structure to represent strings in memory looking like this:
typedef struct {
size_t l;
char *s;
} str_t;
I believe using size_t makes sense for specifying the length of a char string. I'd also like to print this string using printf("%.*s\n", str.l, str.s). However, the * precision expects an int argument, not size_t. I haven't been able to find anything relevant about this. Is there someway to use this structure correctly, without a cast to int in the printf() call?
printf("%.*s\n", (int)str.l, str.s)
// ^^^^^ use a type cast
Edit
OK, I didn't read the question properly. You don't want to use a type cast, but I think, in this case: tough.
Either that or simply use fwrite
fwrite(str.s, str.l, 1, stdout);
printf("\n");
You could do a macro
#define STR2(STR) (int const){ (STR).l }, (char const*const){ (STR).s }
and then use this as printf("%.*s\n", STR2(str)).
Beware that this evaluates STR twice, so be carefull with side effects, but you probably knew that already.
Edit:
I am using compound initializers such that these are implicit conversions. If things go wrong there are more chances that the compiler will warn you than with an explicit cast.
E.g if STR has a field .l that is a pointer and you'd only put a cast to int, all compilers would happily convert that pointer to int. Similar for the .s field this really has to correspond to a char* or something compatible, otherwise you'd see a warning or error.
There is no guarantee that the size_t is an int, or that it can be represented within an int. It's just part of C's legacy in not defining the exact size of an int, coupled with concerns that size_t's implementation might need to be leveraged to address large memory areas (ones that have more than MAX_INT values in them).
The most common error concerning size_t is to assume that it is equivalent to unsigned int. Such old bugs were common, and from personal experience it makes porting from a 32 bit to a 64 bit architecture a pain, as you need to undo this assumption.
At best, you can use a cast. If you really want to get rid of the cast, you could alternatively discard the use of size_t.
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" ...