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]);
}
Related
I am learning C from scratch with Harvard's cs50 course.
I've been given an array that's been initialized this way:
int stuff[9][9];
now I have to handle it.
I want to check if each item of the array exists: if not, make stuff[i][j] = 0, otherwise, stuff[i][j]++
But I am searching without resulting on how to check if the variable I am manipulating exists or is valid or whatever: there is no !!stuff[i][j], nor some typeof stuff[i][j] or comparing if (stuff[i][j] == 'undefined') or NULL or any variations of that which I can use...
So, how can I check if a declared variable has not yet been initialized?
update
I've made a test with this:
int a[3];
for(int i = 0; i < 3; i++)
{
a[i] = a[i] || 0;
}
for(int i = 0; i < 3; i++)
{
printf("a[%i] -> %i\n", i, a[i]);
}
so, if a[i] didn't exist (i.e. had no value assigned to it), it would receive value 0.
this was the output of the printf:
a[0] -> 1
a[1] -> 1
a[2] -> 0
That's good because this approach didn't throw an error, but... what are those numbers??
Assuming the above array is a local variable and not a global, the values of the array are uninitialized and in fact you can't check whether a variable is uninitialized or not, as simply attempting to read such a variable can trigger undefined behavior.
It sounds like you want all array elements to start with the value 0. The simplest way to do this is to initialize the array as such:
int stuff[9][9] = {{ 0 }};
Which explicitly sets element [0][0] to 0 and implicitly sets all other elements to 0.
Alternately, you can create a loop to set all values to 0 to start before doing your "regular" processing.
I'm trying to make an array which have it's element coming from a user input. This array would first have it's size undefined since we don't know how much int would the user input, but then I'm not able to find the amount of element in the array like this unless I put a counter on the loop function.
Here is the code that I've made:
int cross[] = {0};
int k;
for (k = 0; k >= 0; k++){
scanf("%d", &cross[k]);
if (cross[k] == -1){
break; //stop the user from inputing numbers if user input -1
}
int p = sizeof(cross) / sizeof(cross[0]);
If I were to do printf("%d", p), it would always give me 1 as a result. I'm wondering if there is any other way of doing this other than putting a counter on the for loop.
Thanks!!
This phrase from your question is both wrong and dangerous: "This array would first have it's size undefined".
The following line of code defines a fixed-size array that has exactly one element:
int cross[] = {0};
The compiler knows it's one element because you supplied one initializer value {0}. If you supplied this {0, 5, 2}, it would allocate 3 integers, and so on.
This means when you store into cross[k] and k is larger than zero, you're actually exceeding the bounds of your allocated array, which C doesn't catch at compile time, but could cause nasty problems at run time.
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
I was tried to print values of a float array with 7 elements. I assigned only 3 values and they are belong to float, double and integer.
Code:
#include <stdio.h>
int main(){
float array [7];
float f = 3.24;
double d = 23.5;
int i = 4;
array[0] = f;
array[1] = i;
array[2] = d;
int n = sizeof(array)/sizeof(float);
printf("Number of Elements : %d \n\n\n",n);
for(int j = 0; j < n ; j++){
printf("%.2f ,",array[j]);
}
printf("\b ");
}
I got an output as follows :
Number of Elements : 7
3.24 ,4.00 ,23.50 ,-1.#R ,96627196995476105000000000000000.00 ,96629547147269436000000000000000.00 ,0.00
I want to clear is my code correct? And why last four values are different to each other. What are these values?
The last values are known as garbage values in C.
If you do not initialize a variable explicitly in C, it's value could be anything before you explicitly assign something to it. This anything could be garbage; the language standard does not specify what it should be.
You can read this blog for How C compiler decides garbage values: http://blog.aditech.info/2008/02/how-c-compiler-decides-garbage-values.html.
First.
Yes, your code is correct (add return 0 command at the end of your main() function though). However, it needs to be more specific, which leads to your second question.
Second.
C is a language that allows a programmer to do lots of things, but it also requires the programmer to do lots of manual coding.
So, when you declare an array of 7 items, C compiler marks a region of memory to accommodate those items (in this case of the type of float). But it doesn't actually check what that region of memory contains until you explicitly assign the values. In your case the last four values (which you have not assigned yourself) are just garbage left in the region of memory marked for your array.
Once again, compiler does not clear the memory for you when you declare the array, it just marks the region of memory. It's your responsibility to assign default values to the array.
Your possible solution is to manually initialize all of the elements of your array to some default value (for example, a 0), like this:
float array[7] = {0}
I am trying to count the number of elements in an array using C. I tried out the following code. But it just returns 83 every time I run the program. What I mean by to count the number of elements is that I need to know the number of elements that we have entered and not the size of the array.
#include<stdio.h>
#include<stdlib.h>
main(){
int a[100], j = 0, i;
a[0] = '0';
a[1] = '1';
a[2] = '2';
a[3] = '3';
a[4] = '4';
a[5] = '5';
for(i=0; i<100; i++){
if(a[i] == '\0'){
}
else
j = j + 1;
}
printf("%d", j);
system("pause");
}
Arrays in C are a fixed size. They do not expand. Your array has two entries; writing to array[2], array[3], etc. invokes undefined behaviour. In other words, it's invalid code.
If you want to be able to insert an arbitrary number of elements, you will need to use dynamically-allocated memory, manually track how many elements you've inserted, and use realloc when you need to resize.
Since the OP amended his code, here is a more correct reply:
This code works 'by chance', since you didn't initialize the array previously.
It's just 'luck', that somewhere in there, the value 0 comes up.
The declaration of an array does NOT zero it.
Use:
memset(a, 0, 100);
For that. That way, the first 'not overwritten' byte will return '0'.
Reference: http://www.cplusplus.com/reference/clibrary/cstring/memset/
Alternatively, you have to set the 'delimited' manually by adding a[x] = 0;
Now, I know you specifically asked for a 'C' solution, but if you would like to consider using a C++-Compiler, I suggest looking at the stl of C++.
Here's a link to get you started: http://www.cplusplus.com/reference/stl/list/
It's initialized as:
list<char>List;
List.push_back(1);
List.push_back(2);
List.push_back('a');
int j = List.size(); //Returns '3'
do this instead:
main(){
int a[100] = {0};
int j = 0;
int i = 0;
// other stuff
Update based on new code:
In general, you will need a way to identify the end of your array in order to do a correct count. For strings the '\0' is used generally. For other data types you have to come up with your own value to check.
For your specific code example above:
You need to insert a \0 yourself into your array in the last position so that your count will work. (When you create a string like "hello", the '\0' gets automatically put in for you at the end of the string, but not if you create a string character by character).
Alternatively, check for the character '5' to find the end of your current array of characters.
Also, you should break out of the loop once you found the last character, otherwise you are going past the end of the array and will most likely crash (again, if you don't it's sheer luck). I.e., something like:
if(a[i] == '\0'){
break;
}
will work if you do:
a[6] = '\0';
before.
Since C doesn't check array bounds, it might appear that with your current code you seemingly get away with this, but it's sheer luck that the program doesn't crash and may change from run to run. In other words, this is undefined behavior.
Finally, you can of course also use strlen() if you are dealing with strings.