Undefined behavior of a program - c

While writing a program i am filling the entries of a char array with digits. After doing so the length calculated for an array having no zero is correct but for an array starting with zero is zero!
Why is this result coming so!I am not able to interpret my mistake!?
int main()
{
int number_of_terms,no,j,i;
char arr[100];
char c;
scanf("%d",&number_of_terms);
for(i=0;i<number_of_terms;i++)
{
j=0;
while(c!='\n')
{
scanf("%d",&arr[j]);
if(c=getchar()=='\n')
break;
j++;
}
printf("Length is:%d\n",strlen(arr));
}
return 0;
}
for eg if i input my array elements as 4 5
lenght is 2
and if my array elements as 0 5
length is 0..

You are using "%d" in your format specifier, which produces an integer, and you are passing in the address of a character array. This is, exactly like your title says, undefined behaviour. In particular, the value zero will take up 4 of the cells in your string, and will write zero to all of those. Since the character with value zero is the end marker, you get zero length string. However, on another architecture, the second character would probably cause a crash...
If you want to store integers in an array, you should use int arr[...];. If you want to store characters, use "%c".

You are copying the value 0 into the array. This eqals the character '\0' which is used to terminate strings. What you want is to copy the character '0' (has the value 48, see an ascii table).
Change %d to %c to interpret the input has character instead of decimal.
scanf("%c",&arr[j]);
Also your "string" in arr is not zero terminated. After all the characters of your string, you have to end the string with the value 0 (here a decimal is correct). strlen needs it, because it determines the length of the string by traversing the array and counting up until it finds a 0.

Related

How does a null character behave in a char array in C?

I tried to reverse this char array with null characters in the middle and the end, without using string length. (original code)
#include <stdio.h>
#include <stdlib.h>
int main()
{
char string[4] ={'c', '\0', 's', '\0'};
printf("What do we love?\n");
printf("Yes, we love:");
for(int i=3; i>=0; i--){
printf("%d", string[i]);
}
return 0;
}
I expected the output to display nothing. But I got the reverse of the array with whitespaces at the places where I’m guessing are the null characters? (output)
Bcoz I have tried using %d too instead of %c and found that those spaces apparently do have the ascii value of 0. (code with slight change + output + ascii table)
So, does this mean that a loop will not always treat a null character in a char array as an indicator of termination? Does this also mean null characters, which automatically get appended on the empty spaces of a char array actually, get printed as spaces in display, but we just say that it prints nothing in the output after it encounters null character only coz we see 'nothing' on display with most codes?
A null byte is used in a char array to designate the end of a string. Functions that operate on strings such as strcpy, strcmp, and the %s format specifier for printf, will look for a null byte to find the end of a string.
You're not treating string as a string, but as just an array of char. So it doesn't matter whether or not a particular element of the array has the value 0 as you're not treating that value as special in any way. You're just printing the decimal value of each of the elements of the array.

Array showing random characters at the end

I wanted to test things out with arrays on C as I'm just starting to learn the language. Here is my code:
#include <stdio.h>
main(){
int i,t;
char orig[5];
for(i=0;i<=4;i++){
orig[i] = '.';
}
printf("%s\n", orig);
}
Here is my output:
.....�
It is exactly that. What are those mysterious characters? What have i done wrong?
%s with printf() expects a pointer to a string, that is, pointer to the initial element of a null terminated character array. Your array is not null terminated.
Thus, in search of the terminating null character, printf() goes out of bound, and subsequently, invokes undefined behavior.
You have to null-terminate your array, if you want that to be used as a string.
Quote: C11, chapter §7.21.6.1, (emphasis mine)
s
If no l length modifier is present, the argument shall be a pointer to the initial element of an array of character type.280) Characters from the array are
written up to (but not including) the terminating null character. If the
precision is specified, no more than that many bytes are written. If the
precision is not specified or is greater than the size of the array, the array shall
contain a null character.
Quick solution:
Increase the array size by 1, char orig[6];.
Add a null -terminator in the end. After the loop body, add orig[i] = '\0';
And then, print the result.
char orig[5];//creates an array of 5 char. (with indices ranging from 0 to 4)
|?|?|?|0|0|0|0|0|?|?|?|?|
| ^memory you do not own (your mysterious characters)
^start of orig
for(i=0;i<=4;i++){ //attempts to populate array with '.'
orig[i] = '.';
|?|?|?|.|.|.|.|.|?|?|?|?|
| ^memory you do not own (your mysterious characters)
^start of orig
This results in a non null terminated char array, which will invoke undefined behavior if used in a function that expects a C string. C strings must contain enough space to allow for null termination. Change your declaration to the following to accommodate.
char orig[6];
Then add the null termination to the end of your loop:
...
for(i=0;i<=4;i++){
orig[i] = '.';
}
orig[i] = 0;
Resulting in:
|?|?|?|.|.|.|.|.|0|?|?|?|
| ^memory you do not own
^start of orig
Note: Because the null termination results in a C string, the function using it knows how to interpret its contents (i.e. no undefined behavior), and your mysterious characters are held at bay.
There is a difference between an array and a character array. You can consider a character array is an special case of array in which each element is of type char in C and the array should be ended (terminated) by a character null (ASCII value 0).
%s format specifier with printf() expects a pointer to a character array which is terminated by a null character. Your array is not null terminated and hence, printf function goes beyond 5 characters assigned by you and prints garbage values present after your 5th character ('.').
To solve your issues, you need to statically allocate the character array of size one more than the characters you want to store. In your case, a character array of size 6 will work.
#include <stdio.h>
int main(){
int i,t;
char orig[6]; // If you want to store 5 characters, allocate an array of size 6 to store null character at last position.
for (i=0; i<=4; i++) {
orig[i] = '.';
}
orig[5] = '\0';
printf("%s\n", orig);
}
There is a reason to waste one extra character space for the null character. The reason being whenever you pass any array to a function, then only pointer to first element is passed to the function (pushed in function's stack). This makes for a function impossible to determine the end of the array (means operators like sizeof won't work inside the function and sizeof will return the size of the pointer in your machine). That is the reason, functions like memcpy, memset takes an additional function arguments which mentions the array sizes (or the length upto which you want to operate).
However, using character array, function can determine the size of the array by looking for a special character (null character).
You need to add a NUL character (\0) at the end of your string.
#include <stdio.h>
main()
{
int i,t;
char orig[6];
for(i=0;i<=4;i++){
orig[i] = '.';
}
orig[i] = '\0';
printf("%s\n", orig);
}
If you do not know what \0 is, I strongly recommand you to check the ascii table (https://www.asciitable.com/).
Good luck
prinftf takes starting pointer of any memory location, array in this case and print till it encounter a \0 character. These type of strings are called as null terminated strings.
So please add a \0 at the end and put in characters till (size of array - 2) like this :
main(){
int i,t;
char orig[5];
for(i=0;i<4;i++){ //less then size of array -1
orig[i] = '.';
}
orig[i] = '\0'
printf("%s\n", orig);
}

Unexpected output at the end of printing an array of char

#include <stdio.h>
int main(int argc, const char * argv[]) {
  unsigned char ch,i,letters[95];
int tapped [0];
ch=32; //start with 32 (space)
while(ch<=127){
ch++;
letters[i]=ch;
i++;
} 
printf(letters);
return 0;
}
I'm trying to get the ASCII characters from 32 to 127 into an array so I can generate N random ones in another loop.
The issue is that I'm getting back all of them, but I'm also getting back some additional unexpected at the end:
!"#$%&'()*+,-./0123456789:;<=>?#ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~\200\300\367\277_\377
I don't understand why I'm getting \200\300\367\277_\377 at the end, since they aren't in the range. I'm new to C so is there some aspects of arrays that I'm not doing properly?
First, if you count the characters from 32 to 127, there are 96 of them. So letters should be defined with letters[96], not letters[95].
Second, you should not pass letters to printf as the first parameter. The first parameter should be a format string, not a string to be printed literally. In particular, since letters contains a “%” character, it is not a proper format string.
Third, when printing a string, printf expects a null-terminated string by default. To print an array of char that is not null-terminated, you can use a precision in the conversions specifier:
printf("%.96s\n", letters);
Fourth, you say you want all the characters from 32 to 127, but your loop starts with ch set to 32 and increments it before putting it into the array, so the first value put into the array is 33. You should nove the increment to later.
Fifth, you do not initialize i. It must be set to zero before starting the loop.

Printing the value of a 0-initialized array element prints nothing, why?

I have to initialize a char array to 0's. I did it like
char array[256] = {0};
I wanted to check if it worked so I tried testing it
#include <stdio.h>
int main()
{
char s[256] = {0};
printf("%c\n", s[10]);
return 0;
}
After I compile and run it, the command line output shows nothing.
What am I missing ? Perhaps I initialized the array in a wrong manner ?
TL;DR -- %c is the character representation. Use %d to see the decimal 0 value.
Related , from C11, chapter §7.21.6.1, (emphasis mine)
c If no l length modifier is present, the int argument is converted to an
unsigned char, and the resulting character is written.
FYI, see the list of printable values.
That said, for a hosted environment, int main() should be int main(void), at least to conform to the standard.
You are printing s[10] as a character (%c), and the numeric value of s[10] is 0, which represents the character \0, which means end of string and has no textual representation. For this reason you are not seeing anything.
If you want to see the numeric value instead of the character value, use %d to print it as a decimal (integer) number:
printf("%d\n", s[10]);
Note that end of string isn't the same as end of line, as said in one of your comments. End of string means that any string operation over a character sequence must stop when the first \0 arrives. If the character sequence has anything else after \0, it won't be printed, because the string operation stops on the first \0 character.
An end of line is, however, a normal character, which visual effect is to say the terminal or text editor to print the next character after the end of line in a new line.
If you want to have a vector full of end of line characters (and print them as such), you have to travel the vector and fill it:
char s[256];
int i;
for (i = 0; i < 256; ++i)
s[i] = '\n';
printf("%c\n", s[10]);
The ASCII (decimal/numerical) value of the end of line character (\n) is 12, so, the following snippet will be equivalent:
char s[256];
int i;
for (i = 0; i < 256; ++i)
s[i] = 12;
printf("%c\n", s[10]);
That doesn't work however (it doesn't print a new line):
char s[256] = {'\n'}; // or {12};
printf("%c\n", s[10]);
because the effect of {'\n'} is to assign \n to the first element of the array, and the remainings 255 character are filled with value 0, no matter which type of array are you making (char[], int[] or whatever). If you write an empty pair of brackets {}, all the elements will be 0.
So, these two statements are equivalent:
char s[256] = {}; // Implicit filling to 0.
char s[256] = {0}; // Implicit filling to 0 from the second element.
However, without defining the array:
char s[256];
The array is not filling (not initialized), so, each element of s will have anything, until you fill it with values, for example, with a for.
I hope with all of this examples you get the whole picture.

printing int array as string

I am trying to print int array with %s. But it is not working. Any ideas why?
#include<stdio.h>
main() {
int a[8];
a[0]='a';
a[1]='r';
a[2]='i';
a[3]='g';
a[4]='a';
a[5]='t';
a[6]='o';
a[7] = '\0';
printf("%s", a);
}
It prints just a.
I tried with short as well, but it also does not work.
This is because you are trying to print a int array, where each element has a size of 4 byte (4 chars, on 32bit machines at least). printf() interprets it as char array so the first element looks like:
'a' \0 \0 \0
to printf(). As printf() stops at the first \0 it finds, it only prints the 'a'.
Use a char array instead.
Think about the way integers are represented - use a debugger if you must. Looking at the memory you will see plenty of 0 bytes, and %s stops when it reaches a 0 byte.
It prints just a.
That's why it prints just a. Afterwards it encounters a 0 byte and it stops.
Because you declared a as an integer, so those signle characters you initialized would result in an error. You must change it to a char variable. However to save time, just make the variable a pointer using the asterisk character, which then allows you to make a single string using double quotes.
int a[8] means array of 8 ints or 8*(4 bytes) - Say 32 bit architecture
a[0] = 'a' stores in the first int index as 'a''\0''\0''\0'
a[1] = 'r' as 'r''\0''\0''\0' and so on . . .
%s represents any C-style string ie. any string followed by a '\0' character
So
printf("%s", a);
searches for trailing '\0' character and just prints "a" assuming it is the entire string

Resources