In the while loop when *s is mentioned it means the value at the address contained in s, so in the first case, the value will be 'a',
my question is how will while loop checks it, does it checks the ASCII value of the characters to check the condition is true or false ..are some other way?
main()
{
char str[] = "abcd" ;
char *s = str;
while(*s)
printf ("%c",*s++) ;
}
When you declare a string variable like
char str[] = "abcd";
it's like declaring str[5] = "abcd\0";
So, in your while loop, it first checks the value of *s, which is 'a', that translates to 97 on the ascii table. Then you print the current value inside the *s pointer, and then increase the pointer by 1, which leads to the next character. When you reach the \0, the loop exits, because \0 is equal to 0;
while(conditon) in C/C++ code will execute if condition != 0
Since it is a dereferenced char*, this means it is a 1 byte value. Which ranges from 0-255.
Since the first value is 'a' this means it will print this table from values 'a'(61) to 'nbsp' (255) after 255 the char value will overflow to '0' or NULL character at which point the while(condition) will evaluate to false and the program will end.
Related
After assigning 26th element, when printed, still "Computer" is printed out in spite I assigned a character to 26th index. I expect something like this: "Computer K "
What is the reason?
#include <stdio.h>
int main()
{
char m1[40] = "Computer";
printf("%s\n", m1); /*prints out "Computer"*/
m1[26] = 'K';
printf("%s\n", m1); /*prints out "Computer"*/
printf("%c", m1[26]); /*prints "K"*/
}
At 8th index of that string the \0 character is found and %s prints only till it finds a \0 (the end of string, marked by \0) - at 26th the character k is there but it will not be printed as \0 is found before that.
char s[100] = "Computer";
is basically the same as
char s[100] = { 'C', 'o', 'm', 'p', 'u','t','e','r', '\0'};
Since printf stops when the string is 0-terminated it won't print character 26
Whenever you partially initialize an array, the remaining elements are filled with zeroes. (This is a rule in the C standard, C17 6.7.9 ยง19.)
Therefore char m1[40] = "Computer"; ends up in memory like this:
[0] = 'C'
[1] = 'o'
...
[7] = 'r'
[8] = '\0' // the null terminator you automatically get by using the " " syntax
[9] = 0 // everything to zero from here on
...
[39] = 0
Now of course \0 and 0 mean the same thing, the value 0. Either will be interpreted as a null terminator.
If you go ahead and overwrite index 26 and then print the array as a string, it will still only print until it encounters the first null terminator at index 8.
If you do like this however:
#include <stdio.h>
int main()
{
char m1[40] = "Computer";
printf("%s\n", m1); // prints out "Computer"
m1[8] = 'K';
printf("%s\n", m1); // prints out "ComputerK"
}
You overwrite the null terminator, and the next zero that happened to be in the array is treated as null terminator instead. This code only works because we partially initialized the array, so we know there are more zeroes trailing.
Had you instead written
int main()
{
char m1[40];
strcpy(m1, "Computer");
This is not initialization but run-time assignment. strcpy would only set index 0 to 8 ("Computer" with null term at index 8). Remaining elements would be left uninitialized to garbage values, and writing m1[8] = 'K' would destroy the string, as it would then no longer be reliably null terminated. You would get undefined behavior when trying to print it: something like garbage output or a program crash.
In C strings are 0-terminated.
Your initialization fills all array elements after the 'r' with 0.
If you place a non-0 character in any random field of the array, this does not change anything in the fields before or after that element.
This means your string is still 0-terminated right after the 'r'.
How should any function know that after that string some other string might follow?
That's because after "Computer" there's a null terminator (\0) in your array. If you add a character after this \0, it won't be printed because printf() stops printing when it encounters a null terminator.
Just as an addition to the other users answers - you should try to answer your question by being more proactive in your learning. It is enough to write a simple program to understand what is happening.
int main()
{
char m1[40] = "Computer";
printf("%s\n", m1); /*prints out "Computer"*/
m1[26] = 'K';
for(size_t index = 0; index < 40; index++)
{
printf("m1[%zu] = 0x%hhx ('%c')\n", index, (unsigned char)m1[index], (m1[index] >=32) ? m1[index] : ' ');
}
}
When I recently look at some passage about C pointers, I found something interesting. What it said is, a code like this:
char var[10];
char *pointer = &var;
while(*pointer!='\0'){
//Something To loop
}
Can be turned into this:
//While Loop Part:
while(*pointer){
//Something to Loop
}
So, my problem is, what does *pointer means?
while(x) {
do_something();
}
will run do_something() repeatedly as long as x is true. In C, "true" means "not zero".
'\0' is a null character. Numerically, it's zero (the bits that represents '\0' is the same as the number zero; just like a space is the number 0x20 = 32).
So you have while(*pointer != '\0'). While the pointed-to -memory is not a zero byte. Earlier, I said "true" means "non-zero", so the comparison x != 0 (if x is int, short, etc.) or x != '\0' (if x is char) the same as just x inside an if, while, etc.
Should you use this shorter form? In my opinion, no. It makes it less clear to someone reading the code what the intention is. If you write the comparison explicitly, it makes it a lot more obvious what the intention of the loop is, even if they technically mean the same thing to the compiler.
So if you write while(x), x should be a boolean or a C int that represents a boolean (a true-or-false concept) already. If you write while(x != 0), then you care about x being a nonzero integer and are doing something numerical with x. If you write while(x != '\0'), then x is a char and you want to keep going until you find a null character (you're probably processing a C string).
*pointer means dereference the value stored at the location pointed by pointer. When pointer points to a string and used in while loop like while(*pointer), it is equivalent to while(*pointer != '\0'): loop util null terminator if found.
Let's start with a simple example::
int a = 2 ;
int *b = &a ;
/* Run the loop till *b i.e., 2 != 0
Now, you know that, the loop will run twice
and then the condition will become false
*/
while( *b != 0 )
{
*b-- ;
}
Similarly, your code is working with char*, a string.
char var[10] ;
/* copy some string of max char count = 9,
and append the end of string with a '\0' char.*/
char *pointer = &var ;
while( *pointer != '\0' )
{
// do something
// Increment the pointer 1 or some other valid value
}
So, the while loop will run till *pointer don't hit '\0'.
while( *pointer )
/* The above statement means the same as while( *pointer != '\0' ),
because, null char ('\0') = decimal value, numeric zero, 0*/
But the usage can change when you do, while(*pointer != 'x'), where x can be any char. In this case, your first code will exit after *pointer hits the 'x' char but your second snippet will run till *pointer hits '\0' char.
Yes, you can go for it.
Please note that *pointer is the value at the memory location the pointer point to(or hold the address of).
Your *pointer is now pointing to the individual characters of the character array var.
So, while(*pointer) is shorthand usage of the equivalent
while(*pointer!='\0').
Suppose, your string is initialized to 9 characters say "123456789" and situated at an address say addr(memory location).
Now because of the statement:
char *pointer=&var;
pointer will point to first element of string "1234567890".
When you write the *pointer it will retrieve the value stored at the memory location addr which is 1.
Now, the statement:
while(*pointer)
will be equivalent to
while(49)
because ASCII Value of 1 is 49, and condition is evaluated to true.
This will continue till \0 character is reached after incrementing pointer for nine times.
Now, the statement:
while(*pointer)
will be equivalent to
while(0)
because ASCII value of \0 is 0. Thus, condition is evaluated to false and loop stops.
Summary:
In while(condition), condition must be non-zero to continue loop execution. If condition evaluates to zero then loop stops executing.
while(*pointer) will work till the value at memory location being pointed to is a non-zero ASCII value.
Also you can use:
if(*ptr){ //instead of if(*ptr!='\0')
//do somthing
}
if(!*ptr){ //instead of if(*ptr=='\0')
//do somthing
}
*pointer means exactly what it says: "Give me the value that's stored at the place that the pointer points to". Or "dereference pointer" for short. In your concrete example, dereferencing the pointer produces the one of the characters in a string.
while(*pointer) also means exactly what is says: "While the expression *pointer yields a true value, execute the body of the loop".
Since C considers all non-zero values as true, using *pointer in a condition is always equivalent to using the expression *pointer != 0. Consequently, many C programmers omit the != 0 part in order to practice boolean zen.
I was going through a hash function and encountered a condition where the for loop is supposed to exit when a '\0' (NIL) character comes.
unsigned int hash_string (const char *s)
{
register unsigned int i;
for (i = 0; *s; s++) { // This for loop is supposed to end
// when a '\0' comes?
i *= 16777619;
i ^= *s;
}
return i;
}
As far as I know a C-Loop is supposed to end if a condition returns 0.
Here, however, there is no such condition and it still works?
Could someone also tell on what all conditions does a loop succed/fail?
The null character has the value of 0, so in your example, *s will evaluate to zero if it corresponds to the null termination of the character string.
From 5.2.1 Character sets
... A byte with all bits set to 0, called the null character, shall
exist in the basic execution character set; it is used to terminate a
character string.
Then in 6.4.4.4 Character constants
12 EXAMPLE 1 The construction '\0' is commonly used to represent the
null character.
*s de-references the character pointed by s.
If the character code is 0 the loop breaks and it passes for all values other than 0.
\0 is guaranteed to be 0, that why it is guaranteed that loop will terminate at string end when it encounters NUL character.
One of the reason for choosing \0 as string termination in C is to make constructs like this possible.
When *s evaluates to 0 or false, which is convertable from one another, the loop ends.
In fact, the integer representation for character \0 is 0. So it's the same thing.
If I have an array declared as
char arr[1] = "";
What is actually stored in memory? What will a[0] be?
Strings are null-terminated. An empty string contains one element, the null-terminator itself, i.e, '\0'.
char arr[1] = "";
is equivalent to:
char arr[1] = {'\0'};
You can imagine how it's stored in the memory from this.
C-strings are zero-terminated. Thus, "abc" is represented as { 'a', 'b', 'c', 0 }.
Empty strings thus just have the zero.
This is also the reason why a string must always be allocated to be one char larger than the maximum possible length.
arr[0] = 0x00;
however, if you did not assign any value like
char arr[1];
then arr[0] = garbage value
a[0] is the null character, which can be referred to as '\0' or 0.
A string is, by definition, "a contiguous sequence of characters terminated by and including the first null character". For an empty string, the terminating null character is the first one (at index 0).
It will pique more if the array is declared as char arr[] = "";
In this case the sizeof(arr) is 1 and strlen(arr) is 0 .
But still self analysis can be done by adding print like this printf("%d", arr[0]); So that you can understand by yourself.
string is a sequence of characters, in your case there is no character is present inside "". So it stores only '\0' character in arr[0].
C string is end with NULL, so the empty string "" actually is "\0", Compiler help do this,
so strlen("") equal 0 but sizeof("") equal to 1.
Can someone explain how this loop works? The entire function serves to figure out where in hash to place certain strings and the code is as follows:
//determine string location in hash
int hash(char* str)
{
int size = 100;
int sum;
for(; *str; str++)
sum += *str;
return sum % size;
}
It seems to iterate over the string character by character until it hits null, however why does simple *str works as a condition? Why does str++ moves to the next character, shouldn't it be something like this instead: *(str+i) where i increments with each loop and moves "i" places in memory based on *str address?
In C, chars and integers implicitly convert to booleans as: 0 - false, non-zero - true;
So for(; *str; str++) iterates until *str is zero. (or nul)
str is a pointer to an array of chars. str++ increments this pointer to point to the next element in the array and therefore the next character in the string.
So instead of indexing by index. You are moving the pointer.
The condition in a for loop is an expression that is tested for a zero value. The NUL character at the end of str is zero.
The more explicit form of this condition is of course *str != '\0', but that's equivalent since != produces zero when *str is equal to '\0'.
As for why str++ moves to the next character: that's how ++ is defined on pointers. When you increment a char*, you point it to the next char-sized cell in memory. Your *(str + i) solution would also work, it just takes more typing (even though it can be abbreviated str[i]).
This for loop makes use of pointer arithmetic. With that you can increment/decrement the pointer or add/substract an offset to it to navigate to certain entries in the array, since array are continuous blocks of memory you can do that.
str points to a string. Strings in C always end with a terminating \0.
*str dereferences the actual pointer to get the char value.
The for loop's break condition is equivalent to:
*str != '\0'
and
str++
moves the pointer forward to next element.
The hole for-loop is equivalent to:
int len = strlen(str);
int i;
for(i = 0; i < len; i++)
sum += str[i];
You could also write is as while-loop:
while(*str)
sum += *str++;
Why does str++ moves to the next character, shouldn't it be something like this
instead: *(str+i) where i increments with each loop and moves "i" places in
memory based on *str address?
In C/C++, string is a pointer variable that contains the address of your string literal.Initially Str points to the first character.*(str) returns the first character of string.
Str++ points to second charactes.Thus *(str) returns the second character of the string.
why does simple *str works as a condition?
Every c/c++ string contains null character.These Null Characters signify the end of a character string in C. ASCII code of NUL character is 0.
In C/C++,0 means FALSE.Thus, NUL Character in Conditional statement
means FALSE Condition.
for(;0;)/*0 in conditions means false, hence the loop terminates
when pointer points to Null Character.
{
}
It has to do with how C converts values to "True" and "False". In C, 0 is "False" and anything else is "True"
Since null (the character) happens to also be zero it evaluates to "False". If the character set were defined differently and the null character had a value of "11" then the above loop wouldn't work!
As for the 2nd half of the question, a pointer points to a "location" in memory. Incrementing that pointer makes it point to the next "location" in memory. The type of the pointer is relevant here too because the "Next" location depends on how big the thing being pointed to is
When the pointer points to a null character it is regarded as false. This happens in pointers. I don't know who defined it, but it happens.
It may be just becuase C treats 0 as false and every other things as true.
For example in the following code.
if(0) {
puts("true");
} else {
puts("false");
}
false will be the output
The unary * operator is a dereference operator -- *str means "the value pointed to by str." str is a pointer, so incrementing it with str++ (or ++str) changes the pointer to point to the next character. So it is the correct way to increment in the for loop.
Any integral value can be treated as a Boolean. *str as the condition of the for loop takes the value pointed to by str and determine if it is non-zero. If so, the loop continues Once it hits a null character, it terminates.