This question already has answers here:
how does array[100] = {0} set the entire array to 0?
(4 answers)
Closed 6 years ago.
For the famous problem.
There are 100 people standing in a circle numbered from 1 to 100. The first person is having a sword and kills the the person standing next to him clockwise i.e 1 kills 2 and so on. Which is the last number to remain alive? Which is the last number standing?
In the following C code for this problem.
void main(){
int i=0, j; //i has the sword, j gets killed.
int a[N]={0}; //0=not killed
while(1){
if(i != N-1) j = i + 1;
else j = 0;
while(a[j])
if((j + 1) == N) j = 0; //loop back to 0
else j++; //skip over the killed people
if(i==j){ //if i is the only one left, stop
printf("\n\n\n%d is left!", i+1);
return;
}
a[j] = 1; //kill j
printf(" %d kills %d.", i+1, j+1);
if(j != N-1) i = j + 1;
else i=0;
while(a[i])
if((i + 1) == N) i = 0;
else i++;
}
}
Please tell me meaning of int a[N]={0};//0=not killed in line no. 6 Thanks.
In your code,
int a[N]={0};
is initializing all the members of the array a to 0.
As per the C11 standard, chapter §6.7.9, initalization, (emphasis mine)
If there are fewer initializers in a brace-enclosed list than there are elements or members
of an aggregate, or fewer characters in a string literal used to initialize an array of known
size than there are elements in the array, the remainder of the aggregate shall be
initialized implicitly the same as objects that have static storage duration.
and, for intializer value of static storage type int, which is arithmetic type,
[...] if it has arithmetic type, it is initialized to (positive or unsigned) zero;
and a is an array of type int, so it will have all it's members initialized 0 as the values. a[0] will be explicitly initialized to 0 (supplied), and the rest will get the implicit initialization.
FWIW, the N has to be a compile-time constant value, like
#define N 50 //or any value
for this to work.
It basically tells the compiler that this will be an array of size N and will all be zero-initialized. So when you try to show the output of this array you'll see N zeroes.
It is somewhat similar to :
memset(a, 0, N * sizeof(int))
Related
I tried this Armstrong program but found myself entangled in this empty array thing. Working of this program has been bothering me for a while now and still can't seem to figure it what's wrong here. Yea, so just wanted to ask what value are the elements of an empty or incomplete array assigned to? Is it the NULL character i.e. '\0'? I tried checking it on an online C compiler where this assertion seems true but GCC tells us the opposite. I tried this approach to Armstrong problem and here's my code:
#include <stdio.h>
#include <math.h>
int main()
{
int num,i,cub,j;
i = cub = 0;
int sto[20];
scanf("%d",&num);
j = num;
while(num != 0)
{
sto[i] = num%10;
num = num / 10;
i++;
}
i = 0;
while(sto[i] != '\0')
{
cub += pow(sto[i],3);
i++;
}
num = j;
printf("cub: %d num: %d\n\n",cub,num);
if(j == cub)
printf("The number is an Armstrong number");
else
printf("The number is not an Armstrong number");
return 0;
}
I know there is other approach to this problem but what I am looking for is the answer to the above mentioned question.
The values in that array are going to be undefined. They might be zero, they might be whatever values happened to be there from when that portion of the stack was last used. The same principle is applicable to heap memory.
so just wanted to ask what value are the elements of an empty or incomplete array assigned to? Is it the NULL character i.e. '\0'?
No, when declared in the body of a function as you've done it here (i.e. with no initializer), the contents are undefined. In practice, the values will be whatever random data happens to have last been in the stack at those locations. When an "automatic" array is declared as you've done here, the compiler simply inserts a stack increment to reserve space, but does nothing else. It could be zero, but probably not.
You have declared an array in a block scope without storage specifier static
int sto[20];
such an array has automatic storage duration. That is it will not be alive after exiting the block where it is defined.
If you would declare the array in the file scope for example before the function main or with the storage specifier static in a block it would have static storage duration.
From the C Standard (6.7.9 Initialization)
10 If an object that has automatic storage duration is not initialized
explicitly, its value is indeterminate. If an object that has static
or thread storage duration is not initialized explicitly, then:
— if it has pointer type, it is initialized to a null pointer;
— if it has arithmetic type, it is initialized to (positive or
unsigned) zero;
— if it is an aggregate, every member is initialized (recursively)
according to these rules, and any padding is initialized to zero bits;
— if it is a union, the first named member is initialized
(recursively) according to these rules, and any padding is initialized
to zero bits;
C doesn't have an end marker, the Programmer's supposed to handle it. Refer to this link:End of array in C language
Suggestion: Add an end marker in your array, for instance, insert 'x' at the end of your array, and loop until you find the marker. Or just use a counter variable as in this code.
#include <stdio.h>
#include <math.h>
int main()
{
int num,i,cub,j;
i = cub = 0;
int sto[20];
scanf("%d",&num);
j = num;
while(num != 0)
{
sto[i] = num%10;
num = num / 10;
i++;
}
int counter = 0;
while(counter < i)
{
cub += pow(sto[counter],3);
counter++;
}
num = j;
printf("cub: %d num: %d\n\n",cub,num);
if(j == cub)
printf("The number is an Armstrong number");
else
printf("The number is not an Armstrong number");
return 0;
}
I hope this answers your question.
The initial values of sto are indeterminate - they could be pretty much anything, and they can be different each time you run that code.
If you want to make sure all the elements contain a specific value, you can either:
explicitly initialize all 20 elements;
explicitly initialize some elements, with the remainder implicitly initialized to 0;
declare the array with the static keyword to implicitly initialize all elements to 0 (although this changes how the array is allocated and stored);
If you want all elements to initially be 0, you could do one of the following:
int sto[20] = {0}; // explicitly initializes first element to 0, implicitly
// initializes remaining elements to 0
static int sto[20]; // implicitly initializes all elements to 0, *but*
// changes how sto is stored
If you want all the elements to be initialized to something other than 0, then you'll either need to initialize all the elements explicitly:
int sto[20] = {-1, -1, -1, -1, -1, ... };
or use a loop:
for ( size_t i = 0; i < 20; i++ )
sto[i] = -1; // or whatever initial value
I need to populate an array of integers with an unknown number of elements. I am using a while loop to input values and exit the loop as a non integer value is entered. Outside the loop an integer j is initialized at 0 and used to address array elements inside the loop. At each round of the loop I check the value of j before and after the input value is assigned to array element v[j], then j is incremented.
Depending on the size chosen for the array in the declaration, (in the example below v[8]), index j is unexpectedly affected by the assignment itself: in the example below when j equals 11 before the assignment it becomes 2 after the assignment, thereafter messing it all up. As a result the code fails to assign the correct input values to the array.
I am surely lacking some deeper knowledge about C/C++ array management... anyone can help to to fill the gap explaining the apparently strange behaviour of my code?
#include <stdio.h>
int main()
{
int j = 0, m, v[8];
printf("Enter an integer: to finish enter x\n");
while (scanf("%d", &m))
{
printf("j before assignment:%d - ", j);
v[j] = m;
printf("j after assignment:%d - ", j);
printf("v[j] after assignment:%d\n", v[j]);
j++;
}
return 0;
}
You write beyond the array boundaries of v. To avoid this, check j in a for loop, e.g. replace while (...) with
for (j = 0; j < 8 && scanf("%d", &m) == 1; ++j) {
// ...
}
This way, the loop stops after the end of the array (v[7]) is reached.
To comment the "strange" behaviour, read about stack and stack layout, e.g. Does stack grow upward or downward?
As always, check the C tag wiki and the books list The Definitive C Book Guide and List
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
for(int i = 1 ; i <= n ; ++i)
{
scanf("%d" , arr + i);
}
explain this method of taking input in array.
Generally, I try this method for entering elements in array.
for(int i = 1 ; i <= n ; ++i)
{
scanf("%d" , &arr[i]);
}
what is the difference between these two methods?``
I found the former one used in competitive programming...
Here is the "normal" way of using scanf to read n elements into an array:
for(int i = 0; i < n; i++)
scanf("%d", &arr[i]);
Note well that I am calling
scanf("%d", &arr[i]);
with an &, so that I pass a pointer to array[i], so that scanf can fill in that element. (One of the surprising things to remember about scanf is that you must always pass it pointers to fill in, unlike printf, where you pass values to print.)
But if we know how pointers and arrays and pointer arithmetic work, we can then see that this alternative form is equivalent:
scanf("%d", arr + i);
The reason is that when when we mention the array arr in an expression like this, what we get is a pointer to the array's first element. And then arr + i is a pointer to the array's i'th element, which is exactly what we want to pass to scanf, as before.
(Also, you'll notice that I have quietly changed your loop from i = 1; i <= n to i = 0; i < n. Arrays in C are 0-based, so you always want your subscripts to run from 0 to n-1, not from 1 to n.)
The thing is, the second is wrong while the first one is correct - but even then the first one is not robust in that - it doesn't check the return value of scanf().
scanf()'s %d format specifier expects an address of int variable. In the second case you provided the int variable itself (if you enabled compiler warnings this would generate warning message) and the first case you provided the address which results in correct behavior.
In case there are n elements then both of the scanf() would invoke Undefined Behavior because you are accessing an array index out of bound. (Arrays indexing starts from 0 in C).
scanf("%d" , arr + i); is equivalent to scanf("%d",&arr[i]). And the correct way to use scanf() would be
if( scanf("%d", &arr[i]) != 1){
// error occured. Handle it.
}
Also from standard:
d
Matches an optionally signed decimal integer, whose format is the same as expected for the subject sequence of the strtol function with the value 10 for the base argument. The corresponding argument shall be a pointer to signed integer.
To be clear on why both are same:-
The arr+i arr converted to pointer to the first element and then with that pointer we add i - in pointer arithmetic every addition is being directed by the type of element it points to. Here the array is containing int elements - which is why arr+i will point to the i th element of the array. arr+i is a pointer to the ith element which is what is expected by %d format specifier of scanf.
Also &arr[i] - here & address of operator returns the address of the element arr[i] or *(arr+i) which is nothing but the address of the i-th element that is what is being expected by %d format specifier of scanf.
Remember that the argument corresponding to %d in a scanf call must be an expression of type int * (pointer to int). Normally, you'd read an array element as
scanf( "%d", &arr[i] );
The expression &arr[i] evaluates to the address of the element, and it has type int *.
The array subscript operation arr[i] is equivalent to *(arr + i) - given a starting address arr, offset i elements (not bytes!) from that address and dereference the result.
This works because in C, an array expression that isn't the operand of the sizeof or unary & operators is converted ("decays") from type "N-element array of T" to "pointer to T", and the value of the expression is the address of the first element.
Thus, the expression arr by itself will ultimately have type int *, and will evaluate to the address of the first element in the array:
arr == (arr + 0) == &arr[0]
Thus, if
*(arr + i) == arr[i] // int
then it follows that
arr + i == &arr[i] // int *
And this is why
scanf( "%d", arr + i );
works as well as
scanf( "%d", &arr[i] );
As a matter of style, use array subscript notation rather than pointer arithmetic. It conveys the intent more clearly. And, you're less likely to make a mistake with multi-dimensional arrays -
scanf( "%d", &arr[i][j][k] );
is easier to write and understand than
scanf( "%d", *(*(arr + i) + j) + k );
Also, check the result of scanf - it will return the number of items successfully read and assigned, or EOF if end of file has been signaled or there's some kind of input error.
Short version: It's the difference between referring to a value and replacing it with input from the user, and referring to a point in memory and writing to it directly.
In C arrays referring to the name of the variable returns the address of that variable in memory.
The scanf() statement takes input from the user and writes it to a specific point in memory. Applying your second method (the one you are using) you should write something like this:
//YOUR EXAMPLE
#include <stdio.h>
#define n 3
int main()
{
int arr[n];
int i;
printf("Input 3 numbers:\n");
for(i = 0 ; i < n ; i++)
scanf("%d" , &arr[i]);
for(i = 0 ; i < n ; i++)
printf("%d",arr[i]);
}
Here you tell your program to get the value of the array in position i, symbolized by arr[i], and replace that value with the new value obtained from the user.
The other example:
//OTHER METHOD
#include <stdio.h>
#define n 3
int main()
{
int arr[n];
int i;
printf("Input 3 numbers:\n");
for(i = 0 ; i < n ; i++)
scanf("%d" , arr + i);
for(i = 0 ; i < n ; i++)
printf("%d",arr[i]);
}
Here we reference the array by name, meaning we reference to the address of the starting point of where that array is stored in memory. In which case, we do not need the '&' symbol, as we are referring an address directly. The '+ i' term means that every iteration of the loop we refer to the next address in memory in that array (skipping sizeof(int) bytes), and so we write directly to that address.
I don't know for sure which is faster, perhaps these are even equivalent to the compiler, perhaps someone else here would have insights, but both ways would work.
NOTE:
I replaced your for loop boundaries, as you were looping from i=1 to i<=n, and writing to arr[i], which means you weren't utilizing the first element of the array, arr[0], and were out of bounds on arr[n]. (The last cell in the array is arr[n-1].
I am reading K&R, currently on chapter 1. After reading a section and trying to solve the problems, I like to check out for other solutions online just see different methods to tackle the same problem.
Exercise 1-14 says that we need to print an histogram of the frequencies of different characters in its input. This solution I found only takes into consideration alphabet characters:
#include <stdio.h>
#define MAX 122
#define MIN 97
#define DIFF 32
int main(){
int c = EOF;
int i, j;
int array[MAX - MIN];
printf("%d ", MAX - MIN);
for (i = MIN; i <= MAX; i++){
array[i] = 0;
printf("%d ", i);
}
while ((c = getchar()) != EOF){
if (c >= MIN)
++array[c];
else {
++array[c + DIFF];
}
}
for (i = MIN; i <= MAX; i++){
printf("|%c%c|", i - DIFF, i);
for (j = 1; j <= array[i]; j++){
putchar('*');
}
putchar('\n');
}
return 0;
}
While I understand the logic behind this code, I don't understand how or why the array[] array works. When declaring the array, the size of it is 25 (MAX - MIN). This array should be indexed from 0 to 24. However during the first loop, the array is indexed using values from 97 to 122. But how is it possible to access the array if the indexing starts from a value much larger? Shouldn't the loop be
for (i = 0, i < MAX - MIN; i++)
It makes no sense to me how the array could be indexed from
array[97] ... array[122]
EDIT:
I added printf("%d ", MAX - MIN); and printf("%d ", i); in the first loop myself to try to see if it in fact was indexing the array from 97 onwards.
int array[MAX - MIN];
Here, size of array is 25 because 197-97 = 25.
for (i = MIN; i <= MAX; i++){
array[i] = 0;
Here, index of array[i] is out of bound because size of array is 25 and value and MIN is 97.
Also, ++array[c]; and j <= array[i]; is undefined because out of bound.
GCC compiler generated warning:
source_file.c: In function ‘main’:
source_file.c:14:10: warning: array subscript is above array bounds [-Warray-bounds]
array[i] = 0;
^
source_file.c:20:12: warning: array subscript is above array bounds [-Warray-bounds]
++array[c];
^
source_file.c:20:12: warning: array subscript is above array bounds [-Warray-bounds]
source_file.c:28:27: warning: array subscript is above array bounds [-Warray-bounds]
for (j = 1; j <= array[i]; j++){
^
C11 J.2 Undefined behavior
Addition or subtraction of a pointer into, or just beyond, an array object and an integer type produces a result that points just beyond
the array object and is used as the operand of a unary *operator that
is evaluated (6.5.6).
An array subscript is out of range, even if an object is apparently
accessible with the given subscript (as in the lvalue expression
a[1][7] given the declaration int a[4][5]) (6.5.6).
Indeed the for loop is accessing the array out of bounds, invoking Undefined Behavior, which means that your program may crash or not.
MAX - MIN gives 25 and you access the array with indices in [97, 122], which is definetely wrong.
Similarly, ++array[c] and for (j = 1; j <= array[i]; j++) invoke Undefined Behavior as well, since they go out of bounds too.
PS: You need to declare your array with a size of MAX - MIN + 1, since the english alphabet has 26 letters.
There is no boundary checking in C for arrays, it is the responsibility of the programmer to take care of it.
so when you declare an array as
int array[ MAX - MIN ] ;
you are not restricted to use only sizeof( int ) * (MAX - MIN) but then if you don't use within this range behavior is quite erratic.
there are other programming languages that do enforce array boundary check but not c, unless of course it goes through rigorous compilation steps including string warning checks.
so in this case even though the program works it is not correct.
perhaps the bottom line to understand is
"Working code may not always be a correct code"
While loop with scanf get stack overflow after 8 number typed. When less amount, everything is ok. What's the problem?
#include <stdio.h>
main ()
{
int x=0;
int j;
int a [x];
while (scanf("%d\n", &a[x++]) == 1);
for (j = 0; j < x; j++)
printf ("%d element of array is \t%d\n\n", j, a[j]);
return 0;
}
How does code in this topic work? I mean the most accepted answer.
This code causes undefined behavior:
int a [x];
Here, a[] is a variable length array, and x has been initialized to 0. In §6.7.6.2 ¶5 about array declarators of the C11 Draft Standard, can be found:
If the size is an expression that is not an integer constant
expression: if it occurs in a declaration at function prototype scope,
it is treated as if it were replaced by *; otherwise, each time it is
evaluated it shall have a value greater than zero.
Since x evaluates to 0 here, in violation of a "shall" outside of the constraints, this is undefined behavior: anything could happen. That anything could happen includes the possibility that the code appears to work for small array indices. But, as it is, this is not a valid C program.
Note that, even in the absence of the first problem, there is another issue. If, for example, x is instead initialized to 1, then a[] is an array of one int. In this case, the line:
while (scanf("%d\n", &a[x++]) == 1);
leads to undefined behavior, since a[x] is already an out of bounds access with x == 1 when input begins.
You are lucky - after 9. Should be instant.
int a[x] - and x is equal zero. so no storage at all.
if size has to be a variable.
int main (void)
{
int x=0;
int y = 10;
int j;
int a [y];
while (x < y )
read_array_item(&a[x++]);
//for (j = 0; j < y; j++) // or x - it does not matter
//printf ("%d element of array is \t%d\n\n", j, a[j]);
return 0;
}