-4
#include <stdio.h>
int strlength(char s[])
{
    int i;
    while (s[i] != '\0')
    ++i;
    return i;
}
int main()
{
    int x = strlength("abcd");
    printf("%d", x);
    return 0;
}

Im new to StackOver and possibly didn't understand the code formatting (and rules to post questions) correctly. This is a small program from K&R Chapter 2. A little bit modified which doesn't interfere with my problem. Apparently i is initialized before entering while cycle. It works fine I just don't get why? I used onlinegdb online compiler. Maybe is the compiler's "fault" but I don't think this book was written to take into account users compiler. Here is the original form:

int strlen(char s[])
{
    int i;
    
    while(s[i] != '\0')
        ++i;
    return i;
}
  • 3
    It wasn't initialised with `0`. Memory was reserved for it, but it wasn't initialised. If the book example failed to initialise `i` that's a mistake in the book. – Weather Vane Aug 05 '21 at 10:51
  • Since using uninitialized variables is undefined behaviour, memory may or may not be reserved for it; the compiler would be within its rights to discard the entire function – Jiří Baum Aug 05 '21 at 10:56
  • thanks @WeatherVane, i couldn't believe this book has mistakes since it is probably the most popular and overread book about C, and is not the first edition. So my thoughts was that i missed something important. – Mihai Timofti Aug 05 '21 at 11:03
  • 1
    In the second edition at least, the code for `strlen` contains the line `i = 0;` between `int i` and the while loop. – sepp2k Aug 05 '21 at 11:03
  • A lot of things were simpler in the days of K&R, too; no compiler was going to optimise things away, for one thing – Jiří Baum Aug 05 '21 at 11:07
  • BTW: the name `strlen()` is reserved for the library. In fact, all function names starting with `str` (followed by ...) are reserved. This was added in c89/c90 (K&R 2) , after the original K&R. – wildplasser Aug 05 '21 at 11:29
  • 1
    K&R 2nd edition ... page 39 ==> https://i2.paste.pics/8065ee432f9f3fb71f90d2dbc79073f7.png – pmg Aug 05 '21 at 11:56
  • @MihaiTimofti I agree, it's impossible to believe that book has this error. I wonder if you're holding some kind of unauthorized, flawed reproduction. – Steve Summit Aug 05 '21 at 12:17
  • The first edition also has the line `i = 0;` (section 2.3 page 36). There is a scan available on archive.org. – Ian Abbott Aug 05 '21 at 14:49

2 Answers2

1

Its because 0 is already in memory slot where i is pointing. But it wont be 0 every time, it can be anything remained(left over) from last use of that specific memory slot.

Shafqat Jamil Khan
  • 1,039
  • 1
  • 9
  • 17
  • 1
    In principle, the compiler could discard the whole variable and anything that touches it – Jiří Baum Aug 05 '21 at 11:00
  • Are you talking about garbage collection? – Shafqat Jamil Khan Aug 05 '21 at 11:10
  • No, this is about optimisation and undefined behaviour. There is no garbage collection in plain C. – Jiří Baum Aug 05 '21 at 11:16
  • Exactly there is no automatic garbage collection in C thats why it could be anything in uninitialised variable. – Shafqat Jamil Khan Aug 05 '21 at 11:36
  • Since it's undefined behaviour, the compiler is not obliged to even have the variable; it can omit it from the compiled program – Jiří Baum Aug 05 '21 at 11:45
  • I don't think so because C is a compiled language and variable i is being used in next lines of code. – Shafqat Jamil Khan Aug 05 '21 at 11:46
  • 1
    What sabik is telling you is that modern compilers do not merely translate C code directly into corresponding assembly code. They perform semantic analysis of the C code and then seek to generate an optimal sequence of instructions that performs the same semantics as the original C code. When the C code has undefined behavior, its semantics are “anything,” meaning there is no definition for what it does. The optimal assembly code for that is none; an “ideal” compiler will generate whatever minimal amount of code it can, perhaps just a return from `main` or even no code after a `main` label. – Eric Postpischil Aug 05 '21 at 11:47
  • The optimiser can detect that it's not initialized, so it can omit the variable and anything that uses it – Jiří Baum Aug 05 '21 at 11:47
  • 1
    In practice, the undefined behavior may poison only part of a program, such as one code path in an `if … else` or in a `switch`, resulting in the compiler merely deleting that code path and not the others. Or a compiler may retain parts of the code leading up to the undefined behavior even though it is not technically required to, perhaps for quality reasons or other decisions by the implementors. – Eric Postpischil Aug 05 '21 at 11:50
  • 1
    Regardless, the point is, given `int i; while (s[i] != '\0')`, the fact that there is no defined value for `i` when it is used means the compiler may complete eliminate any attempt to reserve any memory for `i` or to perform any load instruction when `i` is used. – Eric Postpischil Aug 05 '21 at 11:50
  • 1
    Thanx @EricPostpischil for the clarification. I will definitely do some research on this topic. Thanks "sabik" for the healthy conversation. – Shafqat Jamil Khan Aug 05 '21 at 11:53
  • 1
    One notable example is CVE-2009-1897 where a NULL pointer dereference (which is also undefined behaviour) poisoned a code path that was actually a necessary check with security implications – Jiří Baum Aug 05 '21 at 12:44
  • Other compilers will define NULL pointer dereference as "program aborts with error"; the resulting program is slightly larger and slower but avoids this surprise – Jiří Baum Aug 05 '21 at 12:57
0

clang catches this if you enable warnings. gcc does not unless you also enable -O2 or higher.

$ clang -Wall -Wextra main.c 
main.c:5:14: warning: variable 'i' is uninitialized when used here [-Wuninitialized]
    while (s[i] != '\0')
             ^
main.c:4:10: note: initialize the variable 'i' to silence this warning
    int i;
         ^
          = 0
1 warning generated.

As you can see, the variable is NOT initialized.

klutt
  • 30,332
  • 17
  • 55
  • 95