Is it necessary to initialize the char array for accurate length? - c

In the below example when I define char array uninitialized and want to find the length, it's undefined behavior.
#include<stdio.h>
int main()
{
char a[250];
printf("length=%d\n",strlen(a));
}
I got "0". I don't know how? Explain it.

Luck. Whether it's good or bad luck is a matter of opinion. The contents of your array are whatever happened to already occupy that memory, and is not initialized. In your case, it happened the first byte was a '\0'.
This is, of course, undefined behavior and you can't depend on it happening this way.

You said in your example you were using an uninitialized char array to show undefined behavior, then when you got "0" you want an explanation? It's... undefined behavior.
If you got 0 for the length if just means that there happens to be a 0 as the first element of a[] in your uninitialized array. When it's an uninitialized local that means, as far as the C standards are concerened, anything can be in there, including a 0.
To address the question in your title: "Is it necessary to initialize the char array for accurate length?"
Yes, to be able to deterministically know the length of a string in a char array via the strlen() function, it is required for a null terminator to be present. That means it needs to be initialized or set in some manner or another.

As other answers say the strlen() result is more a matter of luck than defined behaviour
To find the "size" of the memory block use sizeof() instead
Note: I've also included the string.h and used a long conversion for the integers in the printf
#include<stdio.h>
#include<string.h>
int main()
{
char a[250];
printf("length=%ld\n",strlen(a));
printf("sizeof=%ld\n",sizeof(a));
}

when you define
char a[250];
The array will contains garabage contents and random.
strlen(a) count the number of not null charachter ('\0') till it find a null charachter then it stop.
so if your char a[250]; array contains garabage element and the first element is randomly set to null '\0' the strlen(a) will return 0

Related

strcat() in c language programming

when I run this code I always found a problem in my IDE. Can you give this solution ?
#include<stdio.h>
#include<string.h>
int main(void)
{
char cname[4]="mahe";
strcat(cname, "Karim");
printf("%s",cname);
getch();
return 0;
}
Your array isn't big enough. The original array isn't big enough to hold the null byte at the end of its initial value, so strcat() can't find the end of the string. And then you're adding to it, which writes outside the array. These are both causing undefined behavior.
It needs to be declared large enough to hold the original string, the string you're adding to it, and the trailing null byte. So it has to be at least 10 bytes (4+5+1).
char cname[10] = "mahe";
strcat(cname, "Karim");
printf("%s\n", cname);
Change char cname[4] to char cname[10]. Because you are setting the size 4 and so, you can't append any more to it after adding 4 chars initially.
So, change the size. That's it

Strlen() of allocated pointer

I create a buffer like this but I don't give it content. Then I try to view strlen() of this block memory.
int size = 24;
char *c;
c = (char *)malloc(size);
printf("%d\n", strlen(c));
What I get is not 24 but 40. I try to view the value from c[40] to c[47] and I always get \0 but after c[47] is not null anymore.
When I set size = 18, the result isn't 40 anymore. It's 32. And values from c[32] to c[47] are all \0.
When I set size = 7, the result is 24 and values form c[24] to c[47] are all \0.
I know using strlen for an array like this is not able to give me the size I used in malloc() function.
I just wonder why this happened and when we change the value of size, how the result change? Is there anything we can deal with using this?
Edit: It seem like everyone think the result is unpredictable. It's the fact that it's always a multiple of 8 and when we increase the size, there is a limit where the result increase. We can determine exactly the value of size that make the result change and it doesn't change despite how many times we test. Does it depend on OS not just C language or compiler? Why 8 is chosen?
The memory you allocated isn't initialized. Passing it to strlen, a function that expects a NUL terminated string, has undefined behavior. So you can get whatever, you don't even have to get any result.
There is not built-in way in C to know the exact size of an allocated block of memory.
You should read the documentation, strlen() is for the length of strings. Without much detail I will tell you one thing,
There is no way to get the length of a pointer dynamically, so your only option is to store it and use it later.
A simple elegant method, is to use a struct for that, where you store the size and use it every time you need.
struct pointer_type {
void *pointer;
size_t allocated_size;
};
As for the "What i get is not 24 but 40" question,
Your pointer, is uninitialized. This causes what is known as undefined behavior because the way strlen() works is by dereferencing the pointer and counting characters until a given character occurs, something like
int strlen(const char *const str)
{
int count = 0;
while (*(str++) != '\0') ++count;
return count;
}
and since your pointer points to random garbage, this will not work right and the returned value is unpredictable.

strlen() of an empty array within a struct is not 0

I'm very new to C, and I'm not understanding this behavior. Upon printing the length of this empty array I get 3 instead of 0.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct entry entry;
struct entry{
char arr[16];
};
int main(){
entry a;
printf("%d\n",strlen(a.arr));
return 0;
}
What am I not understanding here?
The statement entry a; does not initialize the struct, so its value is likely garbage. Therefore, there's no guarantee that strlen on any of its members will return anything sensible. In fact, it might even crash the program, or worse.
There is no such thing as an "empty array" in C. Your array of char[16]; always contains 16 bytes - uninitialized as a local variable each char has an unspecified value. In addition, if none of these unspecified values happen to be 0, strlen will read outside the array and your code will have undefined behaviour.
Additionally strlen returns size_t and using %d to print this has undefined behaviour too; you must use %zu where z says that the corresponding argument is size_t.
(If by happenstance you're using the MSVC++ "C" compiler, do note that it might not support %zu. Get a real C compiler and C standard library instead.)
Here's the source code to strlen():
size_t strlen(const char *str)
{
const char *s;
for (s = str; *s; ++s);
return(s - str);
}
Wait, you mean there's source code to strlen()? Why yes. All the standard functions in C are themselves written in C.
This function starts at the memory address specified by str. It then uses the for function to start at that address, and then it goes forward, byte by byte, until it reaches zero. How does that for function do that? Well first it assigns s to str. Then, it checks the value s points to. If it's zero (i.e. if *s returns zero) then the for loop is done. If that value is not zero, the s pointer is incremented, and the zero check is done, over and over, until it finds a zero.
Finally, the distance that the s pointer has moved, minus the original pointer you passed in, is the result of strlen().
In other words, strlen() just walks through memory until it finds the next zero character, and it returns the number of characters from that point to the original pointer.
But, what if it doesn't find a zero? Does it stop? Nope. It will just trudge on and on until it finds a zero or the program crashes.
That is why strlen() is so confusing, and why it's source of many critical bugs in modern software. This doesn't mean you can't use it, but it does mean you must be very very careful to make sure that whatever you pass in is a null-terminated string (i.e. a set of zero or more non-zero characters, followed by a zero character.)
Remember also that in C, you basically have no idea what memory contains when you allocate it or set it aside. If you want it to be all zeros, then you need to make sure to fill it with zeros yourself!
Anyway, the answer to your question involves the use of the memset() function. You'll have to pass memset() the pointer to the beginning of your array, the length of that array, and the value to fill it with (in your case, zero of course!)
No initialization of a, this leads to undefined behavior.
C "strings" are '\0' terminated arrays of char. So strlen() will browse whole memory from given address until it either finds a '\0' or results in a segmentation fault.
What am I not understanding here?
Perhaps the mis-understanding is that auto variables, such as:
entry a;
are assigned memory from the process' stack. The pre-existing content of that stack memory is not zeroed-out for your benefit. Hence the value(s) of the elements of a, which will also be located on the process stack, will not be initially zeroed-out for your benefit. Rather, the entire content of a and its elements (including .arr) will contain bizarre and perhaps unexpected values.
C programmers learn to initialize auto variables by zeroing them out, or initializing them with a desirable value.
For example, the question code might do this as follows:
int main(){
entry a =
{
.arr[0] = 0
};
...
}
Or:
int main(){
entry a;
memset(&a, 0, sizeof(a));
...
}

What is the meaning of the value placed between the braces in char str[]?

To be clear, I'm not asking the difference between char *str and char str[]. I'm even more of a beginner than that. I'm implementing the following code:
// Convert long long to string
char number_str[];
sprintf(number_str, "%lld", number_ll);
When I run printf("%s\n", number_str);, it spits out the correct number, no matter if I put 2 or 256 between those brackets. Which leads me to ask, what are these brackets for?
I was exposed to char str[] in this post.
When I run printf("%s\n", number_str);, it spits out the correct number, no matter if I put 2 or 256 between those brackets. Which leads me to ask, what are these brackets for?
This is because your code invokes undefined behavior. You have not allocated space for your array.
What is the meaning of the value placed between the braces in char str[]?
It means that how much space do you want to allocate for your arrays. But note that when an initializer is used, this value, i.e, length of array (first dimension in case of multidimensional arrays) can be omitted.
In an array declaration, the number between the [ and ] specifies the number of elements in the array.
The code in your question:
char number_str[];
sprintf(number_str, "%lld", number_ll);
is illegal. If it appears inside a function definition, then you cannot use empty brackets; you must specify the size of the array -- and a call to sprintf, or to any other function, can only appear inside a function definition.
If you do specify the size of the array:
char number_str[100];
sprintf(number_str, "%lld", number_ll);
that creates an object number_str which is an array of 100 char elements. If you make the array too small:
char number_str[3];
sprintf(number_str, "%lld", number_ll); /* let's say number_ll == 12345 */
then your program may appear to work, but in fact its behavior is undefined. The sprintf call will attempt to store 6 characters in a 3-character array.
A C compiler is not obliged to diagnose this error. It will very likely let you try to do this, resulting in data being written into memory areas that you don't own.
At file scope, you can declare something like:
extern char array[];
which specifies that an object called array, of type array (of some unspecified size) of char is defined elsewhere.
As a (rather annoying) special case, a function parameter defined with the syntax of an array is actually a pointer:
void func(char param[42]) {
/* param is a pointer; the 42 is silently ignored */
}
Always remember that arrays and pointers are two different things. For an explanation of their admittedly confusing relationship, see section 6 of the comp.lang.c FAQ.

String size is equal to number of characters

I was making a basic program of strings and did this. There is a string in this way:
#include<stdio.h>
int main()
{
char str[7]="network";
printf("%s",str);
return 0;
}
It prints network.In my view, it should not print network. Some garbage value should be printed because '\0' does not end this character array. So how it got printed? There were no warning or errors too.
That's because
char str[7]="network";
is the same as
char str[7]={'n','e','t','w','o','r','k'};
str is a valid char array, but not a string, because it's no null-terminated. So it's undefined behavior to use %s to print it.
Reference: C FAQ: Is char a[3] = "abc"; legal? What does it mean?
char str[7]="network";
This Invokes Undefined behavior.
You did not declared array with enough space
This should be
char str[8]="network";
char str[7]="network";
you did not provide enough space for the string
char str[8]="network";
It's possible that stack pages start off completely zeroed in your system, so the string is actually null-terminated in memory, but not thanks to your code.
Try looking at the program in memory using a debugger, reading your platform documentation or printing out the contents of str[7] to get some clues. Doing so invokes undefined behavior but it's irrelevant when you're trying to figure out what your specific compiler and OS are doing at one given point in time.

Resources