Getting wrong string length - c

I am trying to get the length of a string but i am getting the wrong value, it is saying that it is only 4 characters long. Why is this? am i using sizeof() correctly?
#include <stdio.h>
int main(void)
{
char *s;
int len;
s = "hello world";
len = sizeof(s);
printf("%d\n", len);
}

The sizeof operator is returning the size of the pointer. If you want the length of a string, use the strlen function.
Even if you had an array (e.g. char s[] = "hello world") the sizeof operator would return the wrong value, as it would return the length of the array which includes the string terminator character.
Oh and as a side note, if you want a string pointer to point to literal string, you should declare it const char *, as string literals are constant and can't be modified.

You have declared s as a pointer. When applied to a pointer, sizeof() returns the size of the pointer, not the size of the element pointed to. On your system, the size of a pointer to char happens to be four bytes. So you will see 4 as your output.

In addition to strlen(), you can assign string literal to array of chars
char s[] = "hello world", in this case sizeof() returns size of array in bytes. In this particular case 12, one extra byte for \0 character at the end of the string.
Runtime complexity of sizeof() is O(1).
Complexity of strlen() is O(n).

Related

Is there any way to get the correct size of a string using sizeof function with pointers in C

int main() {
char *s = "hello world!";
printf("%d\n",sizeof(s));
}
I know it will return the size of the pointer. But I want to know is there any way of get the length of a string using sizeof function with pointers.
I don't want you to use (char s[] ) s as an array take it as a pointer
Please reply as soon as possible. I also don't want to use strlen().
Pointers do not keep the information whether they point to a single object or a first element of an array.
Consider the following example
char *p;
char c = 'A';
p = "Hello";
p = &c;
As it is seen the same pointer can point to the string literal "Hello" (its first character) that has the type char[6] and to the single character c.
Usually when a character array is passed to a function it is implicitly converted to pointer to its first element. However if you will pass a pointer to the whole array then you can use the sizeof operator to determine its size.
For example
#include <stdio.h>
void f( char (*p)[6] )
{
printf( "%zu\n", sizeof( *p ) );
}
int main( void )
{
f( &"Hello" );
}
But such an approach has a drawback that in the declaration of the function parameter you have to specify preliminary the size of the accepted array by reference.
So a general approach is declaring function with additional parameter that specifies the size of the passed array if it is required to know the size of the array within the function.
Take into account that a string can be contained in a character array that has much more size than it is required to store the string. So to determine the size of a string itself you should use the standard string function strlen.
There's only one way:
#include <stdio.h>
int main()
{
char s[] = "hello world!";
printf("%s -> %zu\n", s, sizeof s - 1);
}
You need to declare s as an array, not as a pointer, sizeof operator, applied to a pointer, gives you the size of a pointer variable, which is not the size of an array (and it is not what you want).
As you see, I initialize the array in the declaration, so I don't need to put the size between the brackets (this doesn't function with an assignment statement, it must be a declaration with an initializer) And then I subtract one to the size of the array, as the sizeof operator gives me the size of the array (not the string length), and this includes the space for the \0 character at the end.
When you run it:
$ a.out
hello world! -> 12
$ _

C: non-NUL terminated array of chars

I saw here that it isn't possible to find out a (unsigned char *) string length using strlen if it isn't NULL terminated, since the strlen function will go over the string but won't find any '\0', hence a run-time error. I figure that it is exactly the same for string declared with signed char *.
I saw a code snippet that was doing something like int len = sizeof(unsigned char *); but, as I understand, it only gives the size of a pointer - word size. Is it possible to use sizeof in another way to get the result or do I have to get the length somewhere else?
Yes, you have to get the length from somewhere else. A pointer does not include length information and without a convention (e.g. last element is 0), there is no way to tell how long the array is.
non-NUL terminated string
No such thing in C. In C, by definition a string always ends with a null character.
A string is a contiguous sequence of characters terminated by and including the first null character. C11 ยง7.1.1 1
A string is not a pointer. A pointer may point to a string. See below for limitations.
unsigned char *s, signed char *s or char *s are all character pointers. They may contain the address of some character or have a value like NULL. As OP recognizes, sizeof s is the size of the pointer and not the size of the string.
sizeof() can be use to find the size of a string when code uses sizeof some_array_variable. The length will be 1 less than the size is select situations.
strlen() can always be used to find the length of a string. But not all arrays are strings, nor do all character pointers point to a string. See below.
char b[] below is an array and sizeof b will return 6, the size of the array in char units. When b, the formal argument, is passed to strlen(), it is converted to the address of the first element of b and strlen() uses that as its actual argument. strlen() uses that address to find the length. The length of the string is the count of characters, but not inducing the null character '\0', so the result is 5.
char *t below is a pointer assigned the address of the first character to b. Its size, system dependent, is the size of a pointer like 4,8,2, etc. strlen() uses that address like above and the result is 5.
char b[] = "Hello";
char *t = b;
printf("%zu %zu\n", sizeof b, strlen(b)); // 6 5
printf("%zu %zu\n", sizeof t, strlen(t)); // 4 5
Below, in both lines, strlen() is a problem as that function expects a pointer to a string. Instead, it receives a pointer to the beginning of a character array (size 5) that does not contain a null character. The result is undefined behavior. Code may return 5, it may return 100, it may crash the program, it may report differently tomorrow.
char d[5] = "Hello";
char *u = d;
printf("%zu %zu\n", sizeof d, strlen(d)); // 5 *
printf("%zu %zu\n", sizeof u, strlen(u)); // 4 *
In this example, the size of the array is 100, yet the string length is 5. So using sizeof(e) to find the string length does not return a +1 different answer than strlen(e).
char e[100] = "Hello";
char *v = e;
printf("%zu %zu\n", sizeof e, strlen(e)); // 100 5
printf("%zu %zu\n", sizeof v, strlen(v)); // 4 5

How to get the string size in bytes?

As the title implies, my question is how to get the size of a string in C. Is it good to use sizeof if I've declared it (the string) in a function without malloc in it? Or, if I've declared it as a pointer? What if I initialized it with malloc? I would like to have an exhaustive response.
You can use strlen. Size is determined by the terminating null-character, so passed string should be valid.
If you want to get size of memory buffer, that contains your string, and you have pointer to it:
If it is dynamic array(created with malloc), it is impossible to get
it size, since compiler doesn't know what pointer is pointing at.
(check this)
If it is static array, you can use sizeof to get its size.
If you are confused about difference between dynamic and static arrays, check this.
Use strlen to get the length of a null-terminated string.
sizeof returns the length of the array not the string. If it's a pointer (char *s), not an array (char s[]), it won't work, since it will return the size of the pointer (usually 4 bytes on 32-bit systems). I believe an array will be passed or returned as a pointer, so you'd lose the ability to use sizeof to check the size of the array.
So, only if the string spans the entire array (e.g. char s[] = "stuff"), would using sizeof for a statically defined array return what you want (and be faster as it wouldn't need to loop through to find the null-terminator) (if the last character is a null-terminator, you will need to subtract 1). If it doesn't span the entire array, it won't return what you want.
An alternative to all this is actually storing the size of the string.
While sizeof works for this specific type of string:
char str[] = "content";
int charcount = sizeof str - 1; // -1 to exclude terminating '\0'
It does not work if str is pointer (sizeof returns size of pointer, usually 4 or 8) or array with specified length (sizeof will return the byte count matching specified length, which for char type are same).
Just use strlen().
If you use sizeof()then a char *str and char str[] will return different answers. char str[] will return the length of the string(including the string terminator) while char *str will return the size of the pointer(differs as per compiler).
I like to use:
(strlen(string) + 1 ) * sizeof(char)
This will give you the buffer size in bytes. You can use this with snprintf() may help:
const char* message = "%s, World!";
char* string = (char*)malloc((strlen(message)+1))*sizeof(char));
snprintf(string, (strlen(message)+1))*sizeof(char), message, "Hello");
Cheers! Function: size_t strlen (const char *s)
There are two ways of finding the string size bytes:
1st Solution:
# include <iostream>
# include <cctype>
# include <cstring>
using namespace std;
int main()
{
char str[] = {"A lonely day."};
cout<<"The string bytes for str[] is: "<<strlen(str);
return 0;
}
2nd Solution:
# include <iostream>
# include <cstring>
using namespace std;
int main()
{
char str[] = {"A lonely day."};
cout<<"The string bytes for str[] is: "<<sizeof(str);
return 0;
}
Both solution produces different outputs. I will explain it to you after you read these.
The 1st solution uses strlen and based on cplusplus.com,
The length of a C string is determined by the terminating null-character: A C string is as long as the number of characters between the beginning of the string and the terminating null character (without including the terminating null character itself).
That can explain why does the 1st Solution prints out the correct string size bytes when the 2nd Solution prints the wrong string size bytes. But if you still don't understand, then continue reading.
The 2nd Solution uses sizeof to find out the string size bytes. Based on this SO answer, it says (modified it):
sizeof("f") must return 2 string size bytes, one for the 'f' and one for the terminating '\0' (terminating null-character).
That is why the output is string size bytes 14. One for the whole string and one for '\0'.
Conclusion:
To get the correct answer for 2nd Solution, you must do sizeof(str)-1.
References:
Sizeof string literal
https://cplusplus.com/reference/cstring/strlen/?kw=strlen

ANSI C - count the size of the string pointer

Is it possible to create string variables using pointers? So that I don't have to pass its size everytime, like char x[4] = "aaa"?
How can I get the size of such string?
And can I initialize an empty string with a pointer?
Remember that strings in C are ended by the null terminator character, written as \0. If you have a well-formed string stored in your pointer variable, you can therefore determine the length by searching for this character:
char *x = "hello"; // automatically appends a null terminator
int len = 0;
while (x[len] != '\0') {
len++;
}
If your variables are uninitialized or otherwise not well-formed (e.g., by being NULL) you obviously cannot take this approach; however, most functions are generally written under the assumption that the strings are well-formed, because this leads to faster code.
If you wish to initialize a pointer, you have three options: NULL, a valid address (e.g., char *x = &someCharVar), or a string constant (e.g., char *x = "hello"). Note that if you use a string constant, it is illegal for you to write into that pointer unless you re-assign to it with the address of a non-constant string.
// Get enough space for 24 characters plus null terminator
char *myString = (char*) malloc(25 * sizeof(char));
strcpy(myString, "some text"); // fill the new memory
fgets(myString, 25, stdin); // fill with keyboard input
Note that sizeof(char) is unnecessary here, since a char is always defined to be exactly 1 byte. However, it's a good habit to get into for when you're using other data types, and it helps make your code self-documenting by making your intentions very clear.
If you're initializing an array of char with a string literal, you don't need to specify the size:
char str[] = "This is a test";
This will create str as a 15-element array of char (the size is taken from the length of the initiliazer, including the 0 terminator) and copy the contents of the string literal to it.
A string literal is an array expression of type "N-element array of char" (const char in C++). Except when it is being used to initialize an array in a declaration (such as above) or is the operand of the sizeof or unary & operators, an expression of type "array of T" will be converted to an expression of type "pointer to T", and the value of the expression will be the address of the first element of the array.
If you write
const char *str = "This is a test";
the expression "This is a test" is converted from type "15-element array of char" to "pointer to char", and the value of the expression is the address of the first character, which is written to the variable str.
The behavior on attempting to modify the contents of a string literal is undefined; some platforms store string literals in read-only memory, some do not. Some map multiple occurrences of the same string literal to a single instance, others don't. It's best to always treat a string literal as unmodifiable, which is why I declared str as const char * instead of just char *.
To get the length of a string, use strlen:
char str[] = "This is a test"; // or const char *str = "This is a test";
size_t len = strlen(str); // or strlen("This is a test");
This will return the number of characters in the string up to (but not including) the 0 terminator; strlen("This is a test") will return 14.
To get the size of the buffer containing the string, you would use the sizeof operator:
char str[] = "This is a test";
size_t len = sizeof str; // or sizeof "This is a test"
Note that this won't give you the size of the buffer if you declared str as a pointer, such as
const char *str = "This is a test";
In that case, sizeof str; only gives you the size of a char *, not the string it points to.

Another way for string creation in C? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
C -> sizeof string is always 8
I found the following way to create a string:
#include <stdio.h>
#include <string.h>
int main(void) {
char *ptr = "this is a short string";
int count = sizeof ptr / sizeof ptr[0];
int count2 = strlen(ptr);
printf("the size of array is %d\n", count);
printf("the size of array is %d\n", count2);
return 0;
}
I can't use the the usual way to get the length by sizeof ptr / sizeof ptr[0], Does this way to create string is valid? Any pros and cons about his notation?
When you do this
char *ptr = "this is a short string";
ptr is actually a pointer on the stack.
Which points to string literal on the readonly memory.
[ptr] ----> "This is a short string"
So trying to get the sizeof ptr will always evaluate to size of int on that particular
machine.
But when you try this
char ptr[]="this is a short string";
Then actually for whole string the memory is created on the stack with ptr having
starting address of the array
|t|h|i|s| |i|s| | |a| |s|h|o|r|t| |s|t|r|i|n|g|\0|
|' '| ==> this is atually a byte shown in above diagram and ptr keep the address of |t|.
So size of ptr will give you the size of whole array.
Because ptr is a pointer and not an array. If you used char ptr[] instead of char *ptr, you would have gotten an almost-correct result - instead of 22, it would have resulted in 23, since the size of the array incorporates the terminating NUL byte also, which is not counted by strlen().
By the way, "creating" a string like this is (almost) valid, but if you don't use a character array, the compiler will initialize the pointer with the address of an array of constant strings, so you should really write
`const char *ptr`
instead of what you have now (i. e. add the const qualifier).
Yes, using strlen to get the size of a string is valid. Even more, strlen is the proper way to get the size of a string. The sizeof solution here is even wrong. sizeof ptr will return 8 on 64 bits system because it is the size of a pointer, divided by the size of a char, which is 1, you will obtain only 8.
The only case where you can use sizeof to get the size of a string is when it is declared as an array of character (char[]).
This code will crash if you modify the string (because recent compilers see it as a constant). Besides, it gives incorrect results as sizeof(ptr) returns the pointer size rather than the string size.
You should rather write:
char ptr[] = "this is a short string";
Because this code will let you find the sctring length as well as modify the string contents.

Resources