\0 when initializing a char array with a loop - arrays

I need to initialize a char array with a loop and print it. Just like that:
int main( void )
{
char array[ 10 ];
for( int i = 1; i < 10; ++i ) {
array[ i - 1 ] = i;
}
// array[] contains numbers from 1 to 9 and an unitialized subscript
printf( "%s", array );
}
I want to know if I need to put the '\0' character in array[ 9 ] or if it is already there.
In other words: once I declared char array[ 10 ]; does the last subscript contains '\0' ?
I searched for similar questions and the better I could find is this where the array is filled with a loop but till the end, leaving no space for the terminating character.
Please tell me the truth.

In other words: once I declared char array[ 10 ]; does the last subscript contains '\0' ?
No.
You define a local variable and do not initialize it. These variables are not initialized by default but hold indetermined values.
If you want to have a defined value, you need to initialize or assign it:
char array[ 10 ] = "";
This will define an array with 10 elements.
As there is an initializer, the first element will be set to 0 (=='\0') due to the provided string literal.
Furthermore all other elements will be set to 0 because you provide less initializer values than you have elements in your array.

once I declared char array[10]; does the last subscript contains '\0' ?
The answer is NO: when you define the array as an automatic variable (a local variable in a function), it is uninitialized. Hence none of its elements can be assumed to have any specific value. If you initialize the array, even partially, all elements will be initialized, either explicitly from the values provided in the initializer or implicitly to 0 if there are not enough initializers.
0 and '\0' are equivalent, they are int constants representing the value 0. It is idiomatic to use '\0' to represent the null byte at the end of a char array that makes it a C string. Note that '0' is a different thing: it is the character code for the 0 digit. In ASCII, '0' has the value 48 (or 0x30), but some ancient computers used to use different encodings where '0' had a different value. The C standard mandates that the codes for all 10 digits from 0 to 9 must be consecutive, so the digit n has the code '0' + n.
Note that the loop in your code sets the value of 9 elements of the array to non zero values, and leaves the last entry uninitialized so the array is not null terminated, hence it is not a C string.
If you want to use the char array as a C string, you must null terminate it by setting array[9] to '\0'.
Note also that you can print a char array that is not null terminated by specifying the maximum number of bytes to output as a precision field in the conversion specifier: %.9s.
Finally, be aware that array[0] = 1; does not set a valid character in the first position of array, but a control code that might not be printable. array[0] = '0' + 1; set the character '1'.
#include <stdio.h>
int main(void) {
char array[10];
/* use the element number as the loop index: less error prone */
for (int i = 0; i < 9; ++i) {
array[i] = `0` + i + 1;
}
// array[] contains numbers from 1 to 9 and an unitialized subscript
printf("%.9s\n", array); // prints up to 9 bytes from `array`
array[9] = '\0';
// array[] contains numbers from 1 to 9 and a null terminator, a valid C string
printf("%s\n", array); // produce the same output.
return 0;
}

once I declared char array[ 10 ]; does the last subscript contains '\0' ?
No. It's uninitialized. It has garbage values in every element from whatever code used the same piece of memory last.

NO, You dont need to put '\0' at the end that is array[9].
why?
because when an array (char,int,float) is uninitialized it contains garbage values.
After initializing partial or full all other elements becomes 0 or \0 in case of char array.
example:
char array[10];
all elements contains garbage value.
after intialization
char array[10]={'a' ,'b'}; all other elements automitically becomes '\0'
this is true in case of structures also.

Related

Inner workings of c language as it pertains to character arrays

I’m wondering why this code prints a zero.
int x = 10;
char newChar[x];
printf(“%d\n”,strlen(newChar));
strlen() computes the amount of characters in a string. It counts characters up to the null character \0, which terminates a string. It returns the amount of characters read up to but not including that null character.
In your provided example the char array newChar is uninitialized; it has no string in it.
Thus, the output shall be 0.
The behavior is per standard undefined, when using uninitialized objects. In production code, Always initialize objects or, in the case of VLAs like newChar is, assign its elements with "placeholder" values or use strcpy (with VLAS of char) to copy an empty-string ("") into it, before using them in any manner.
Technically, it is possible that strlen() will return a value different than 0 on a different machine or already at a different execution of the program just because the behavior is undefined -> one or more elements could have a non-zero value followed by an element with a 0 value - making the pseudo-string effect perfect.
Maybe you wanted to calculate the number of elements in newChar.
Therefore, sizeof instead of strlen() would be appropriate:
int x = 10;
char newChar[x];
printf("%zu\n", sizeof(newChar) / sizeof(*newChar));
Online example
#include <stdio.h>
int main(void)
{
int x = 10;
char newChar[x];
printf("The number of elements in newChar is: %zu\n", sizeof(newChar) / sizeof(*newChar));
}
Output:
The number of elements in newChar is: 10

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);
}

Declare a whole string with a single charcter

When declaring an array in C I can write int array[100]={0} and it assigns 0 to all index. Is there any way to do the same thing with string? Because when I write char string[100]={'A'} it only assigns 'A' to the first index.And when I print the string it displays "A" instead of what I want "AAAAA.....A(99 times)". I dont want to use a loop to assign all the indexes with 'A'. So what can I do?
Its not in the standard but some compilers (including gcc and clang that I tested it with on my system) allow this:
#include <stdio.h>
int main(){
char str[100] = {[0 ... 98] = 'A'};
str[99]='\0'; // this line is really not necessary, since default is 0 and I just wrote it for clarity
printf("%s\n", str);
return 0;
}
Standard C does not have a mechanism for what you want. In particular, note that the two cases you describe are the same: that int array[100]={0} causes the array to be initialized with all zeroes is not because the specified 0 is applied to all elements, but rather that the specified 0 is applied to the zeroth element, and all otherwise uninitialized elements are initialized with a default value, which coincidentally is specified to be 0. Initialization of the char array follows the same rule.
If you want to initialize 99 elements of an array to 'A', then the initializer must provide 99 'A's. If you want to avoid typing (and counting) them all, then you might use a macro to assist:
#define REPEAT11(x) x x x x x x x x x x x
char string[100] = REPEAT11("AAAAAAAAA");
That makes use of compile-time concatenation of adjacent string literals to form the wanted initializer.
You could also use memset() from <string.h> to fill the first n bytes of your array with 'A' characters. Here is an example:
#include <stdio.h>
#include <string.h>
#define SIZE 100
int main(void) {
/* initializes all elements to 0. */
/* Will not work with 'A' as the default values of this array are 0 */
char array[SIZE] = {0};
/* fills first 99 bytes with 'A', and leaves last byte as '\0' */
memset(array, 'A', sizeof(array)-1);
printf("array = %s\n", array);
printf("length of array = %zu\n", strlen(array));
/* Outputs:
array = AAAAAAAAA...
length of array = 99
*/
return 0;
}

Array element as an index to a different array

I came across some examples where an array is indexed based on values from a different array.
Example:
char s[] = "aloha";
int l= strlen(s);
int array_count[256];
memset(array_count,0,256*sizeof(int));
for(int i=0;i<l;i++)
{
array_count[s[i]]++;// What exactly happens in this statement ??
}
I understood it as it checking and setting the alphabets in s[] as 1's in the array array_count,which is the alphabet set. Is that right ?
The code is keeping a histogram of how many times a given character appears in the string. Every time a character appears in the string, the array element corresponding to the ASCII value of that character is incremented by one.
The elements in array_count [] are all set to 0 by your memset(). Then your loop iterates through s[]. So in the first iteration:
array_count [s[i]]++ // first evaluate [i]
array_count [s[0]]++ // i is zero
array_count ['a']++ // s[0] is 'a'
array_count [97]++ // promotion of 'a' from char to int; ASCII value of 'a' is 97
array_count [97] is zero because of the memset, so because of the ++ it gets incremented to 1.
Similar magic happens with the rest of the characters in subsequent iterations; when the loop terminates, array_count [97] will be 2 because of the two 'a's in "aloha"; array_count [0] will be 1 because of the NUL character at the end of "aloha"; and you can figure out what the rest of the array will be (mostly zeros).
Each char in s[] has an unsigned int value (usually it's ascii value) inclusively between 0 and 255. array_count[] is initialised to all zeros by the memset. Then, by iterating through s[] from start to end with i in the for loop, the value of each char is used to index into array_count[] and increment it's value with ++. So you get a count of the char values in s[].
256 is possible letter in string. see the ascii table.
http://www.asciitable.com/
for(int i=0;i<l;i++)
{
array_count[s[i]]++; // What exactly happens in this statement ??
for i=0
s[i] = 'a'
ascii value of 'a' is 97
so it will increment arry_count[97] value from 0 to 1
}

Undefined behavior of a program

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.

Resources