I don't understand why strlen() is giving wrong value (ie: 9) only for the first string. After that the values are coming correctly.
#include <stdio.h>
#include <string.h>
int main() {
int m, i, j;
i = 2;
j = 5;
char a[i][j];
for (i = 0; i <= 2; i++) {
scanf("%s", a[i]);
}
m = strlen(a[0]);
printf("%d\n", m); //here the problem is coming//
m = strlen(a[1]);
printf("%d\n", m);
m = strlen(a[2]);
printf("%d\n", m);
return 0;
}
INPUT:
heyman
jack
bro
OUTPUT:
9
4
3
Each row of a is only 5 bytes. When you read heyman into a[0], it overflows into a[1]. So you have:
a[0] = "heyma"
a[1] = "n\0"
Then when you read into a[1], you have
a[0] = "heyma"
a[1] = "jack\0"
Notice that there's no null terminator in a[0]. So when you call strlen(a[0]), it goes past the end of a[0] and continues searching in a[1] for the null byte. There are 5 bytes in a[0] and 4 bytes in a[1], so the length is 9. Technically, this is undefined behavior, but this is what happens in actual implementations because 2-dimensional arrays are contiguous.
In addition, when you read into a[2] you're completely outside the a array, resulting in undefined behavior.
Since your array has length [2][5] you can store a maximum of 2 words of length 4, every word also has the terminating character \0 in addition to its letters.
You having as input heyman means you are writing too many letters and don't have enough space to also store the \0. Either try with a shorter word or change your length from 5 to 7.
Also you are storing 3 words in your array of length 2, the length refers to the number of elements stored not to the number you can go up to. Length 2 will have available positions 0 and 1 so when you are passing as input the third word you are trying to write outside of the array bounds.
Related
I am a beginner to C and I was asked to calculate size of an array without using sizeof operator. So I tried out this code, but it only works for odd number of elements. Do all arrays end with NULL just like string.
#include <stdio.h>
void main()
{
int a[] = {1,2,3,4,5,6,7,8,9};
int size = 0;
for (int i = 0; a[i] != '\0'; i++)
{
size++;
}
printf("size=%d\n", size);
}
No, in general, there is no default sentinel character for arrays.
As a special case, the arrays which ends with a null terminator (ASCII value 0), is called a string. However, that's a special case, and not the standard.
> So I tried out this code, but it only works for odd number of elements.
Try your code with this array -
int a[] = {1,2,0,4,5,6,7,8,9};
^
|
3 replaced with 0
and you will find the output will be size=2, why?
Because of the for loop condition - a[i] != '\0'.
So, what's happening when for loop condition hit - a[i] != '\0'?
This '\0' is integer character constant and its type is int. It is same as 0. When a[i] is 0, the condition becomes false and loop exits.
In your program, none of the element of array a has value 0 and for loop keep on iterating as the condition results in true for every element of array and your program end up accessing array beyond its size and this lead to undefined behaviour.
> Do all arrays end with NULL just like string.
The answer is NO. In C language, neither array nor string end with NULL, rather, strings are actually one-dimensional array of characters terminated by and including the first null character '\0'.
To calculate size of array without using sizeof, what you need is total number of bytes consumed by array and size (in bytes) of type of elements of array. Once you have this information, you can simply divide the total number of bytes by size of an element of array.
#include <stdio.h>
#include <stddef.h>
int main (void) {
int a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
ptrdiff_t size = ((char *)(&a + 1) - (char *)&a) / ((char *)(a + 1) - (char *)a);
printf("size = %td\n", size);
return 0;
}
Output:
# ./a.out
size = 9
Additional:
'\0' and NULL are not same.
I've written a code to find the number of elements in an integer array as follows:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int arr[] = {2, 3, 5, 5};
int i;
for(i = 0; i < 4; i++)
{
printf("%d %d\n", &arr[i], arr[i]);
}
printf("%d", &arr[i - 1] - arr);
return 0;
}
The last printf prints 3 as opposed to 4 which is the number of elements in the array. Why does the code print one less than the no of elements in the array?
You pass the wrong format specifier to printf. So whatever output you get in the loop is the result of undefined behavior. To print a pointer correctly and portably you must use the %p specifier and pass a void*:
printf("%p %d\n", (void*)&arr[i], arr[i]);
The reason the last printf prints 3 (even though the format specifier is maybe wrong again), is because that's the offset between the the last cell in the array and the beginning. That's what you calculate, so remember that the last cell is indexed with offset 3.
The result of subtracting two pointers can be captured in the type ptrdiff_t. And to print that you'd need the %td format specifier, if we are to make your code more portable again:
printf("%td", &arr[i-1]-arr);
To calculate the array length, you'd need to subtract a pointer to "one passed the end" element of the array (don't worry, calculating that address is not undefined behavior) and a pointer to the beginning. Applying that to the print statement after your loop
printf("%td", (arr + i) - arr);
Which quite expectantly, is just i (4).
Your last printf need correction for specifiers as in your case the difference in first and last position address can easily fit in int but caan produce undefined behaviour so use td specifier as difference in address is of ptrdiff_t type. The problem is that how you calculate your length of array, keep in mind that indexing is done from zero that is if you have array length of 4, last index would be 3 and
array length according to your code is 3 - 0 = 3
but actually it should be 3 - 0 + 1 = 4
change your outside printf to
printf("%td",&arr[i-1] - arr + 1);
I hope this would help you. Also you printf in your for loop needs correct specifier as you are trying to print the address instead of int.
I am studying for my midterm. this was an example code
#include <stdio.h>
void doubleArray(int array[], int length)
{
for (int i = 0; i < length-2; i++) {
array[i] += array[i];
}
length += 5;
printf(“%d\n”, length); // Question 29
}
int main(int argc,char *argv[]) {
int integers[6] = { 3, 4, 5, 6, 7, 8};
int length = 6;
printf(“%d\n”, integers[4]); // Question 28
doubleArray(integers, length);
printf(“%d\n”, *(integers + 3)); // Question 30
printf(“%d\n”, *(integers + 4)); // Question 31
printf(“%d\n”, length); // Question 32
}
for questions 30 and 31
the answer is that it prints 12 (30) and 7 (31)
can someone explain to me why and what that "*(integers + 3)" means?
* is a dereference operator on a pointer.
This means that it will "get" the value that's stored at the pointer address of the item right after it ((integers + 3)).
It will interpret this value as the dereferenced type of the item after it (int since (integers + 3) is of type int*)
(integers + 3)
integers is a pointer to the address of the first element of the integers array.
That means that if integers contained [1, 2, 3, 4, 5] then it would point to where 1 is stored in memory.
integers + 3 takes the address of integers (i.e. where 1 is stored in memory) and adds the amount of address space required to store 3 ints (since the pointer is of type int*). Advancing it by one space would give you the address of 2 in memory, advancing it by two spaces would give you the address of 3 in memory, and advancing it by three spaces gives you the address of 4 in memory.
How this applies to your example
(integers + 3) gives you the address of the 4th item in the integers array since it's the first element's address plus the size of three elements.
Dereferencing that with the * operator, gives you the value of the 4th element, 12 (since the value of 6 was doubled by doubleArray)
The same applies to *(integers + 4) except that doubleArray didn't double the 5th element so it gives you 7.
How doubleArray works
for (int i = 0; i < length-2; i++) means start the variable i at 0 and advance it until it is length - 2.
This means it takes the value of everything from 0 to the value of length - 2 but executes the body of the loop for values from 0 to length - 3 since the < is exclusive (the conditional is evaluated BEFORE executing the body of the loop so when i == length - 2 the condition is false and the loop terminates without further execution.
So, for each element, excluding the last two, the element in array is added to itself.
I am reading through K&R 2nd Edition and C by Dissection 4th Edition, and came to arrays where they both didn't explicitly state it but I remember from a class that we want to always initialize an array to zero to circumvent garbage being in the indices from previous memory allocations.
I looked online and similar suggestions were made, but I saw an array declaration/initialization I hadn't seen before so I wanted to test it: int x[size]={0}; found here
I wrote a little c program to check things out, and I'm currently going down the rabbit hole it seems.
Can someone please help explain the output?
gcc is compiling to c99, -std=c89 won't compile (because of // type comments so I know it isn't c89 (ansi) ), but looking at the gcc flags I cannot find STDC_VERSION flag to tell me which is; therefore, I've manually compiled like: gcc -Wall -std=c99 -o arrayTest arrayTest.c
The little program is:
#include <stdio.h>
typedef int bool;
#define true 1
#define false 2
#define DEBUG_ true
int main()
{
int x[5] ={0};// what does this do? Guess: Initialize x[0]-x[4] values of 0?
int i=0;// for loop
printf("Hello, World!\n");
if(DEBUG_){
printf("TESTING FOR NULLITY OF INDICES\n");
for(i=0; i<5; i++){
if(x[i]==NULL) printf("The Value at %d is NULL\n", i);
}// If each is null, thats what int x[5]={0} decl/initl does..
// Is 0 NULL in C Language (I wouldn't have thought so..)
}
printf("assigning 0 to all indices of the array..\n");
for(i=0; i<5; i++){ x[i]=0; }
// assigning the array to zeros..
if(DEBUG_){
printf("printing contents of array after filling with zero's\n");
for(i=0; i<5; i++){ printf(x[i]+"\n"); }
// hopefully print out 5 zeros..
printf("SUSPECTING THAT ZERO FILL DIDN'T REPLACE NULL VALUES IN ARRAY\n");
for(i=0; i<5; i++){
if(x[i]==NULL) printf("The Value at %d is NULL\n", i);
}
}
printf("Filling the array, each index has value i*2\n");
for(i=0; i<5; i++){ x[i]= i*2; }
// initialize the array to i*2.
// Expected Values 0, 2, 4, 6, 8
for(i=0; i<5; i++){ printf(x[i]+"\n"); }
// hopefully print out Expected Values
return 0;
}
The output from the program:
-bash-4.3$
-bash-4.3$ arrayTest
Hello, World!
TESTING FOR NULLITY OF INDICES
The Value at 0 is NULL
The Value at 1 is NULL
The Value at 2 is NULL
The Value at 3 is NULL
The Value at 4 is NULL
assigning 0 to all indices of the array..
printing contents of array after filling with zero's
SUSPECTING THAT ZERO FILL DIDN'T REPLACE NULL VALUES IN ARRAY
The Value at 0 is NULL
The Value at 1 is NULL
The Value at 2 is NULL
The Value at 3 is NULL
The Value at 4 is NULL
Filling the array, each index has value i*2
USPECTING THAT ZERO FILL DIDN'T REPLACE NULL VALUES IN ARRAYPECTING THAT ZERO FILL DIDN'T REPLACE NULL VALUES IN ARRAYCTING THAT ZERO FILL DIDN'T REPLACE NULL VALUES IN ARRAY
From the looks of that last line there is a repeating sequence occurring:
USPECTING THAT ZERO FILL DIDN'T REPLACE NULL VALUES IN ARRAY
PECTING THAT ZERO FILL DIDN'T REPLACE NULL VALUES IN ARRAY
CTING THAT ZERO FILL DIDN'T REPLACE NULL VALUES IN ARRAY
I am not sure why this is occurring.
Specifically can someone explain what the array declaration/initialization actually does, why assigning zeros to the array isn't working in this case, why trying to set each index to i*2 doesn't work, and what is going on with the print pattern at the end of the output?
The printf() usage is wrong here. Change
printf(x[i]+"\n");
to
printf("%d\n", x[i]);
See the man page for details.
Also, regarding the initializaion, if you need any reference, see this.
According to the C Standard (6.7.9 Initialization)
21 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.
This means that in this declaration
int x[5] ={0};
the first element of the array is explicitly initialized by 0 and all other elements of the array are implicitly initialized the same way as objects with static storage duration that is they are also initialized by 0.
If you would wriite for example
int x[5] ={1};
then the elements of the array would be initialized like { 1, 0, 0, 0, 0 }
Also take into account that this statement
printf(x[i]+"\n");
does not do what you expect. In this expression x[i]+"\n" there is used the pointer arithmetic becuase string literal "\n" is converted to pointer to its first character and after adding to the pointer value x[i] can result in undefined behaviour. I think you mean
printf( "%d\n", x[i] );
Here is a more interesting example of initializing odd elements of an array with 1 and even elements with 0 which you do not know yet..
#include <stdio.h>
int main(void)
{
int a[] = { [1] = 1, [3] = 1, [5] = 1 };
printf( "The number of elements in the array is %zu\n",
sizeof( a ) / sizeof( *a) );
for ( size_t i = 0; i < sizeof( a ) / sizeof( *a ); i++ )
{
printf( "%d ", a[i] );
}
printf( "\n" );
return 0;
}
The program output is
The number of elements in the array is 6
0 1 0 1 0 1
Thus if for example you want to initialize only the last element of an array with 1 and all other elements with 0 you can write
int a[] = { [4] = 1 };
Output of the program:
#include <stdio.h>
int main()
{
int size;
printf("Enter the size of array: ");
scanf("%d",&size);
int b[size],i = 0;
printf("Enter %d integers to be printed: ",size);
while(i++ < size)
{
scanf("%d",&b[i]);
printf("%d %d\n", i, b[i]);
}
return 0;
}
for size = 5 and input numbers :
0 1 2 3 4
is
1 0
2 1
3 2
4 3
5 4
where first column is for i and second for elements of array b.
It is clear that i in the loop while(i++ < size) { incremented to 1 before entering the loop. This loop should have to store/print the value at/of b[1], b[2], b[3], b[4] but not b[5] as loop will terminate at i = 5.
How this code is printing the value of b[5]?
I have tested it for different array size and it is not printing any garbage value.
By reading and writing past the array, your program invokes undefined behavior. It doesn't mean that it has to crash or print garbage values, it can pretend working fine. Apparently, that's what is happening in this case.
In your loop, the condition i < size is checked before i is incremented. But, i is incremented before entering the body of the loop and not after it, so it is possible to access b[5] in this case, as i would be incremented after checking i < size with i=4. You do not want that, as this causes undefined program behavior.
If you try to access an element in the array which does not exist, e.g. array[size], you are accessing the next spot in the memory right after the array. In this case you are lucky, but if this meant you were accessing a part of the memory where your program isn't allowed to do so, you'd get a segmentation fault.
you could use a for cycle instead of a while so instead of while(i++<size)you could use for(i = 0; i < size; i++) that should solve your problem my friend :)