Confusing output of two different Char Array - c

Problem : Although I declared two char strings , whose contents are the same , Outputs are different.
#include <stdio.h>
int main(void)
{
/* Initialization of two different array that We deal with */
char arr1[10]={'0','1','2','3','4','5','6','7','8','9'};
char arr2[10]="0123456789";
/* Initialization End */
for(int i = 0 ; i < 11 ; ++i)
{
printf("arr1[%d] is %c \t\t",i,arr1[i]);
printf("arr2[%d] is %c\n",i,arr2[i]);
if(arr1[i]=='\0')
printf("%d . character is \\0 of arr1 \n",i);
if(arr2[i]=='\0')
printf("%d . character is \\0 of arr2 \n",i);
}
return 0;
}
Expectation : I expected that both if statements are going to be true for any kind of value of 'i'.
Output : It is an output that I got it.
arr1[0] is 0 arr2[0] is 0
arr1[1] is 1 arr2[1] is 1
arr1[2] is 2 arr2[2] is 2
arr1[3] is 3 arr2[3] is 3
arr1[4] is 4 arr2[4] is 4
arr1[5] is 5 arr2[5] is 5
arr1[6] is 6 arr2[6] is 6
arr1[7] is 7 arr2[7] is 7
arr1[8] is 8 arr2[8] is 8
arr1[9] is 9 arr2[9] is 9
arr1[10] is 0 arr2[10] is
10 . character is \0 of arr2

Both cases invoke undefined behavior by accessing the array out of bounds. You cannot access index 10 of an array with items allocated from index 0 to 9. Therefore you need to change the loop to i<10 or anything might happen. It just happened to be different values printed - because you have no guarantees of what will be printed for the byte at index 10.
In both examples, there is no null terminator, so they are equivalent. Due to a subtle, weird rule in the C language (C17 6.7.9/14 emphasis mine):
An array of character type may be initialized by a character string literal or UTF−8 string
literal, optionally enclosed in braces. Successive bytes of the string literal (including the
terminating null character if there is room or if the array is of unknown size) initialize the
elements of the array.
Normally when trying to store too many initializes inside an array, we get a compiler error. But not in this very specific case with a string literal initializer, which is a "language bug" of sorts. Change to char arr2[9]="0123456789"; and it won't compile. Change to char arr2[11]="0123456789"; and it will work just fine, even when iterating over 11 elements.

There are a few small things wrong with your code and the assumptions you seem to make about it.
1. These two declarations are not the same
char arr1[10]={'0','1','2','3','4','5','6','7','8','9'};
char arr2[10]="0123456789";
The second line is equal to this:
char arr2[10]={'0','1','2','3','4','5','6','7','8','9', 0x00};
... which defines an array containing 11 elements. Check out implicit zero-termination for string literals.
EDIT:
I'm getting quite a lot of down-votes for this point specifically. Please see Lundin's comment below, which clarifies the issue.
2. Your for-loop iterates over 11 elements
for(i=0 ; i<11 ;++i)
The loop above goes through i = 0..10, which is 11 elements.... but you only wanted to compare the first 10 right?
You could change your loop to only compare the first ten elements [for(i = 0; i < 10; ++i)] and that would make your program work as you expect.
Because of what it seems you are assuming, I would recommend reading up on strings in C, array-indices and undefined behavior.

when a character array is initialized with a double quoted string and array size is not specified, compiler automatically allocates one extra space for string terminator ‘\0’
Ref

Related

Why my program prints the wrong character?

Hey I am trying to understand pointers and I create a program in which I give words from keywords and I
store them in an array and after that I want to print the first character of the first word (I expected) but it prints the first character of the second word
What is going wrong?
#include<stdio.h>
#include<stdlib.h>
int main ()
{
int i=0;
char array[5][10];
for(i = 0 ; i < 5 ; i++)
{
gets(array[i]);
}
printf("\n");
char *p;
p=&array[0][10];
printf("%c",*p);
return 0;
}
The position in the array you are looking for doesn't exist, so the program is showing a random value.
The arrays go from 0 to (n-1), 'n' being 5 or 10 in your case. If you search a differente position in the range of the array you will find the correct answer.
Try changing this part of the code ('a' have to be a value from 0 to 4 and 'b' have to be a value from 0 to 9)
p=&array[a][b];
pointer are address in memory
1rst word adresses are from 0 to 9
2nd word from 10 to 19
p=&array[0][10]; points to the 10th elt so the first letter of the second word! and not for a random value as previous post suggests.
That said NEVER use gets
Why is the gets function so dangerous that it should not be used?

Odd and even number using switch case

I want to print the value as well as its type
Input:
1
3
5
78
10
Output:
Odd 1
Odd 3
Odd 5
Even 78
Odd 11
#include <stdio.h>
int main()
{
int a[4],b,c;
for(b=0 ; b<=4 ; b++)
{
scanf("%d",&a[b]);
}
for (c=0 ; c<=4 ; c++)
{
switch (a[c]%2)
{
case 0 :
printf ("Even %d\n",a[c]);
break;
case 1 :
printf ("Odd %d\n",a[c]);
break;
}
}
return 0;
}
Why is the last output Odd 11 instead of Even 10?
You only have to change the declaration of a[4] into a[5] for having a correct program. The boundaries of the iterations are correct.
What happens when you run your code is that the four first input values go into the array a[4] and the fifth one into the variable b which is allocated immediately behind the array, in your case. This is a programming error and gives unpredictible results, depending on how the compiler is allocating memory.
In your case, we can conclude that the variable b is stored behind the array a[4], and is incremented once after you store the fifth element into what you think is the array. The place where this happens is the b++ statement of the for loop.
I couldn't reproduce this behaviour because my compiler probably doesn't allocate b immediately behind a[4].
You made the array of the size 4 but you are entering 5 values in it.
So you could just increase the array size or make the loop enter 4 values by exchanging <= with < sign.
Hope it helps.
You are entering five numbers, not four. Change int a[4] to int a[5]. Then optionally change all your conditions to <5 for clarity, as this is usually what C programmers expect.

When assign element of array to another, unexpected value contained

I'm learning C language by my self.
When I assign one array value of element to another, (looks) strange thing happens.
My Code is below.
int main(void){
int i =0;
char a2[] = "aaaa";
char a1[] = "bbb";
printf("%lu\n",sizeof(a2));
printf("%lu\n",sizeof(a1));
printf("%c\n",a2[4]);
printf("---\n");
for(i =0; i < sizeof(a2); i++){
a2[i]=a1[i];
printf("%c\n", a2[i]);
}
printf("---\n");
printf("%c\n", a2[4]);
return 0;
}
result is below.
5
4
---
b
b
b
b
---
b
I have no idea why a[4] a2[4] value is "b".
Firstly, I thought that if I try to compile this code, compiler would through error, but it says OK.
So I show the result and saw the a2[4] element contain "b" character.
How array works in C?
What should I have to learn the notion for the deeper understand of mechanism?
As it has already been pointed out when you do the following you will get undefined behavior:
for(i =0; i < sizeof(a2); i++){
a2[i]=a1[i];
printf("%c\n", a2[i]);
}
This is because the size of a2 is 5 and the size of a1 is 4 so you have accessed the fifth element of a1 (a1[4]) which is going beyond the array. So when you do a2[4] = a1[4], which is what the last iteration of your for loop is doing you could be assigning any value to a2[4] since the value of a1[4] is not well defined. So even though a2[4] is a valid element in the array you have assigned something to it that is not well defined and when you print a2[4] you could be printing anything. See the last paragraph for an explanation of why you are most likely getting b.
There are a few things to remember with this. First arrays are zero based indexed and second strings in C are null terminated so sizeof("aa") is actually 3 not 2.
Since your program has undefined behavior it could print anything as any value could be in a1[4]. Having said that if the compiler placed the array a2 right after a1 you would consistently see b printed as you assigned the value b to a2[0] in the first iteration of your loop. This is just one possible explanation for why you are seeing a b. The compiler does not have to place the arrays in this position and in fact on my machine it does not place the arrays in this position. This is what it means when behavior is undefined in C.
"why a[4] value is "b"" is incorrect. (Certainly OP means a2 here.)
Note that the size of a2 is printed as 5. The following does not access outside the array bounds of a2. Instead code is simply printing the null character '\0' initially, and then ....
char a2[] = "aaaa";
....
printf("%c\n",a2[4]);
Code enters undefined behavior with the below loop in the last iteration as a2[4] = a1[4]; accesses a1 outside its 4 char size. So the rest of code behavior is undefined.
char a1[] = "bbb";
...
for(i =0; i < sizeof(a2); i++){
a2[i]=a1[i];
printf("%c\n", a2[i]);
}

C: attempting to invert the order of 10 words in a matrix

I have a matrix of 10 lines and 20 columns; so I ask the user to enter with 10 words and put each word in one line of the matrix. In the next step, I must create another matrix (with the same proportions) in a way that the first word of the first matrix is at the last word of the second matrix, the second word of the first matrix is at the penultimate word of the second matrix, and so on.
But I'm getting some problems with the code:
#include <stdio.h>
int main() {
char str[10][20], str2[10][20];
int i, j=9;
/* filling the first matrix */
for(i =0;i <10;i++){
scanf("%s",str[i]);
}
/* copying to the second matrix in an inverted order */
for (i=0;i<10;i++, j--){
str2[i] = str[j];
}
return 0;
}
It returns the following error: incompatyble types when assigning to type 'char[20]'from type 'char*'
at the line:
"str2[i] = str[j]"
Ideas?
If you say
char str2[10][20];
then str2 is a two dimensional array of chars, specifically it is 200 chars arranged in 10 rows of 20 chars.
If you declare str2 that way, then str2[i] is equivalent to a pointer to a char, but it is not an assignable pointer. In other words, that pointer can only be used on the right side of an equals sign, not the left side of an equals sign.
If you want an array of pointers, you must declare the array as
char *str2[10];
In this case, str2 is a one dimensional array of pointers-to-char. Specifically it is an array of 10 pointers (which will occupy 40 bytes of memory on a 32-bit machine).
So there's the distinction, char str2[10][20] occupies 200 bytes of memory and has no assignable pointers, whereas char *str2[10] occupies 40 bytes of memory and has 10 assignable pointers.
In c you cannot write(assign) to arrays in their entirety, like the commentor said you should use strcopy (memcpy if its not strings) for this purpose.

Subtracting two strings in C

Well , I was actually looking at strcmp() , was confused about its working . Anyways I wrote this code
#include <stdio.h>
main()
{
char a[5] = "ggod";
char b[5] = "ggod";
int c = 0;
c = b - a;
printf("%d value", c);
}
and I get the output as
16
Can anyone explain Why is it 16 ?
What you have subtracted there are not two strings, but two char *. c holds the memory address difference between a and b. This can be pretty much anything arbitrary. Here it just means that you have 16 bytes space between the start of the first string and the start of the second one on your stack.
c = b - a;
This is pointer arithmetic. The array names it self points to starting address of array. c hold the difference between two locations which are pointed by b and a.
When you print those values with %p you will get to know in your case
if you print the values looks like this a==0x7fff042f3710 b==0x7fff042f3720
c= b-a ==>c=0x7fff042f3720-0x7fff042f3710=>c=0x10 //indecimal the value is 16
Try printing those
printf("%p %p\n",a,b);
c=b-a;
if you change size of array difference would be changed
char a[120]="ggod";
char b[5]="ggod";
b is an array object
a is also an array object
an array object is a static address to an array.
so b-a is adifference between 2 addresses and not between the 2 strings "ggod"-"ggod"
If you want to compare between 2 string you can use strcmp()
strcmp() will return 0 if the 2 strings are the same and non 0 value if the 2 strings are different
here after an example of using strcmp()

Resources