2

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
chqrlie
  • 131,814
  • 10
  • 121
  • 189
Pranshu_Taneja
  • 186
  • 1
  • 1
  • 16
  • 2
    You can only have strings up to `4` characters because `j == 5`. – Barmar Jul 21 '20 at 08:44
  • 2
    `heyman` is writing out of bounds. – Barmar Jul 21 '20 at 08:44
  • why only 4 as j=5 i.e-(0-5) which will give me max 6 character to input.?? help? – Pranshu_Taneja Jul 21 '20 at 08:51
  • 1
    @fly_high `j=5` will give you 5 characters to write, from `0` to `4`, but strings need to have an additional character `\0` at the end otherwise `C` doesn't know that the string is actually over. That means that from your maximum length you have to subtract `1` to account for this terminator `\0` – John Doe Jul 21 '20 at 08:53
  • 1
    @fly_high `a[5]` means you have positions `a[0], a[1], a[2], a[3], a[4]` available, i.e. `5` spaces not that the array will go up to `a[5]` – John Doe Jul 21 '20 at 08:57
  • ok ok actually i was understanding in a way of as like rows as in row i have written a[2] so it goes from 0-2(0,1,2) but this is not in the case of column right....?@John Smith – Pranshu_Taneja Jul 21 '20 at 09:02
  • 2
    Rows and columns are the same. An array `a[2]` has only 2 elements with index `0..1`. – Gerhardh Jul 21 '20 at 09:14
  • ok ok now i get it... – Pranshu_Taneja Jul 21 '20 at 09:15
  • Please remember, in C, offsets start with 0, so the valid index into an array is 0...(number of elements in array -1) – user3629249 Jul 22 '20 at 18:16

2 Answers2

10

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.

Barmar
  • 741,623
  • 53
  • 500
  • 612
  • 1
    I wonder if overflowing from `a[0]` into `a[1]` is ub (obviously doing anything with `a[2]` is). – Paul Hankin Jul 21 '20 at 08:54
  • @PaulHankin I think I've read conflicting answers about it. – Barmar Jul 21 '20 at 08:55
  • wow that was really interesting and i got all of the idea....thanks @Barmar – Pranshu_Taneja Jul 21 '20 at 09:05
  • 3
    Appendix J.2 in the standard explicitly lists this kind of out of bounds multi-dimensional array access as an example of undefined behaviour: `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])` – M. Nejat Aydin Jul 21 '20 at 09:06
  • 1
    It is UB when it overflows into `a[1]` – Lxer Lx Jul 21 '20 at 09:12
7

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.

John Doe
  • 1,613
  • 1
  • 17
  • 35