The default value of an uninitialized static int is zero. What about if the datatype is a char?
#include<stdio.h>
int main()
{
static char i;
printf("%c", i);
return 0;
}
This program executes without giving any output - why?
In your example, i is default initialized to zero, and when you output that as a character using printf with the %c format you are outputting the null character \0, which is why you don't see anything.
If you wanted to see the numerical value, you should use printf("%i", (int)i)
In C static variables are auto initialized.
If it's of integer number type, like int, etc… It will be initialized to 0.
If it is of floating number type like float, etc... It will be initialized to 0.0.
If it's of char type then it will be initialized with null character, \0.
If it's of pointer type it will get it's default value as NULL
Related
I came across an example of non-portable C code where a char pointer is an argument to a variadic C function. The example is described in the image below. The part highlighted in blue is not necessarily clear, and appears wrong. In particular, I have two questions:
Assuming that NULL was 32-bit int 0 on a system, wouldn't compiler do an implicit cast of 32-bit - int to 64-bit 0 when it encounters char *string = NULL. If not, then are we saying that each expression like char *string = NULL is non-portable and must be always replaced with an explicit cast like char *string = (char *)NULL for portable C?
If NULL was 32-bit int 0, and char *string was 64-bit then why would printf run out of bits to print like it is suggested in the blue highlight. Shouldn't printf get full 64 bits as it was passed string and not NULL.
Source of the screenshot: https://wiki.sei.cmu.edu/confluence/plugins/servlet/mobile?contentId=87152357#content/view/87152357
The referenced article is wrong and should be disregarded.
Assuming that NULL was 32-bit int 0 on a system, wouldn't compiler do an implicit cast of 32-bit - int to 64-bit 0 when it encounters char *string = NULL.
An assignment automatically converts the right operand to the type of the left operand. So char *string = NULL will convert the NULL value to char *, not to “64-bit 0”.
If not, then are we saying that each expression like char *string = NULL is non-portable and must be always replaced with an explicit cast like char *string = (char *)NULL for portable C?
No, char *string = NULL is portable C code; it is strictly conforming.
If NULL was 32-bit int 0, and char *string was 64-bit then why would printf run out of bits to print like it is suggested in the blue highlight. Shouldn't printf get full 64 bits as it was passed string and not NULL.
The code referenced, char* string = NULL; followed by printf("%s %d\n", string, 1);, does not pass NULL to printf. It passes string to printf, and the prior assignment converts NULL to char *. So printf is passed a char * that has the value of a null pointer. This will not cause any problem in interpreting the variable arguments to printf. (It is, however, improper to pass a null pointer for the %s conversion.)
If the call were instead printf("%s", NULL);, then there is a problem. Arguments corresponding to the ... part of a variable-argument function are not automatically converted to a parameter type. They are processed by the default argument promotions, which largely promote narrow integer types to int and promote float to double, but they will not convert an int to any type of pointer. Thus, if NULL is defined as 0, then printf("%s", NULL); passes an int where a char * is expected, and this may cause various misinterpretations of the arguments.
In consequence, never use the NULL macro as a direct argument to a function with a variable argument list. Using a pointer variable that has been assigned from NULL is okay.
I'm currently trying to learn C, with some prior experience in Python and
pointer arithmetic is really confusing me right now.
#include <stdio.h>
int main()
{
char *s[] = {"String1", "Literal2", "Pointers3"};
printf("%c", s[1]+1);
return 0;
}
Why does it print m instead of i ?
When I replace the format string with %s it does what I expect and prints out iteral2(Go to the 0th index of the 1st string literal then move 1 memory adress forward and print the rest).
How does this work, why does it print out a seemingly arbitrary character instead of the 1st(or 1th?) index when I use the %c format string.
The %c format specifier expects a character, not a pointer to a character. The expression s[1] evaluates to a pointer to a character, pointing to "Literal2", and the expression s[1]+1 also evaluates to a pointer to a character, pointing to "iteral2".
So, you are passing printf() a pointer to a character, and you are telling it to print a character. So, what is happening is that the pointer is being re-interpreted as a character, and the output is garbage.
If you insert a character into "String1", (making it, say, "String11",) then everything will be moved upwards in memory by one location, so the value of the pointer will be greater by 1, and so it might print n instead of m.
To obtain a character, when all you have is a pointer to a character, you need to dereference the pointer. So, that would be "%c", *(s[1]+1).
#include <stdio.h>
int main() {
const char *s[] = {"String1", "Literal2", "Pointers3"};
printf("%c", s[1][1]);
return 0; }
Also i think you should make s[] constant as it's deprecated.
I'm trying to write a simple function that will convert a number to a string with respect to a given format, something like this:
char * write_number(const char *format, void *number) {
char mystring[50];
sprintf(mystring, format, number);
return mystring;
}
The only problem is that this works with the integer data type, but not with the float/double data type. Is there any way to make this work regardless of the data type.
Thanks!
Addition to the original question:
Thank you for your suggestions. I didn't manage to make it work, here is the complete example of what am I trying to get.
#include <stdio.h>
void write_number(const char *format, void *number) {
char mystring[50];
sprintf(mystring, format, *number);
printf("%s\n", mystring);
}
int main(void) {
int a = 10;
float b = 20;
double c = 40;
write_number("int: %03d", &a);
write_number("float: %6.2f", &b);
write_number("double: %6.2f", &c);
return 0;
}
The format string for sprintf specifies the data type, eg "%i" prints and integer and "%f" prints a float - hence you would need to change the format string depending on the data type.
Note also that the function is not guarnetied to work for ints either, since its returning a pointer to a local variable mystring, this will go out of scope when the function returns and can be overwritten at any time by another value, so then the returned pointer will be pointing to some random value rather than the string.
For the calling code to use the address of the local variable mystring[] is undefined behavior.
"why does this work with integer data type?"
Undefined behavior does not mean code "won't work". It does does not mean if it works today (with integer) , it will work tomorrow. It means the behavior is not defined.
sprintf already takes care of the types of its arguments; you just need to make sure that the format string you pass to it matches it arguments. For example, "%f", 3.125f to format a float, "%d", 12 to format a signed integer, "%e", 3.125 to format a double precision float. Try reading this.
Your function won't work anyway, though, as compilation errors will tell you. mystring is declared as a local variable on the stack, so it will cease to exist when your function returns.
Also, you are passing the address of number to sprintf instead of its value. To pass the value, you need to dereference it like this: sprintf(mystring, format, *number);
You function may work with an integer type because pointers are integral, so if you called write_number("%d\n", 55), you would be passing a pointer to memory address 55, which sprintf would interpret as an integer because of the %d. If your ints and void *s weren't the same size this wouldn't work.
To actually pass a pointer instead of an int casted to a pointer do something like this:
char *str;
float num = 8.375f;
str = write_number("%f", &num);
#include <stdio.h>
int main()
{
char a[8];
printf("%d\n",a) ;
return 0;
}
For the above code the output was this :- 2686744
What is the reason behind this output?
I found that the output doesn't depend on the content of the array, but on the size of the array.I just want the explanation.
char a[8];
printf("%d\n",a);
This code has undefined behavior.
The array expression a is implicitly converted to a char* value, equivalent to &a[0]. That value is then passed to printf -- but since the %d format requires an int argument, the behavior is undefined.
If int and char* happen to have the same size, and if they're passed as function arguments using the same mechanism, then it will likely print a decimal representation of the address of (the initial element of) the array.
But don't do that. If you want to print the address:
printf("%p\n", (void*)a);
You are printing the address of the array as an integer.
If you compile with -Wall to enable warnings your compiler should complain about that.
#include<stdio.h>
int main(void) {
char a = "any"; //any string
printf("%c", a);
getch();
}
Why always d (for %c) or 100 (for %d) gets printed? What's happening?
char a="any"; is not declaring any string. Your compiler should through error/warning. You need
const char *a = "any";
Now
printf("%c", *a);
will print character a as pointer a is pointer to the first element of the string literal any.
Your code has issues. On
char a="any";
the string literal "any" is a pointer but you are saving it in a (small) integer type. Because the value of a is (part of) an address it will have an essentially arbitrary value. On my machine it prints "T" (if I remove the getch() line because that doesn't compile).
GCC gives the following warning:
warning: initialization makes integer from pointer without a cast
and whatever compiler you are using probably tells you something similar. You should really take this warning seriously.
"something between double quotes"
Allocates memory for the string and returns a pointer to the string in memory. you need to store this pointer in a using char *a = "abc"; now 'a' is a pointer to the string abc.
printf("%s",a) this will print the entire string abc.
for a single character use single quotes 'a' in this case char a = 'b'; is correct.
printf("%c",a) this will print b.
printf("%d",a) this will print the ascii value of 'b', which is 98
In the statement
char a = "any";
the string literal "any" evaluates to the address of its first character which is of type const char *. Assigning a const char * to a char variable implicitly converts the pointer to an integer. This emits the following warning if you compile with -W gcc flag:
warning: initialization makes integer from pointer without a cast [enabled by default]
What happens next is the least significant byte of the cast integer value is assigned to the char variable a. This is a random value and cannot be predicted. On my machine, it happened to be the ascii code for the character /. On your machine, it happened to be 100, the ascii code for the character d. It is just pure chance. Nothing else.
You should assign a string literal to a const char * as:
const char *a = "any";
and print the string pointed to by a by the %s conversion specifier as:
printf("%s\n", a);
Also note that getch is not a C standard library function, so your program won't compile on a linux machine. You can use getchar for the same effect, though.