C - Dynamically allocate an array of char - c

What is the size of dynamic memory allocated for array?
for example we have to print an array of len = 4
int i, n, len = 4;
char *s = malloc(len * sizeof(char));
strcpy(s, "aaabbcc");
n = strlen(s);
printf("%d", n);
The output should be 4 but all the time output is 7.

In C, you have to allocate fixed size buffers for data. In your case, you allocated len * sizeof(char), where len = 4 bytes for your string.
From the documentation on strcpy:
char * strcpy ( char * destination, const char * source );
Copy string Copies the C string pointed by source into the array
pointed by destination, including the terminating null character (and
stopping at that point).
To avoid overflows, the size of the array pointed by destination shall
be long enough to contain the same C string as source (including the
terminating null character), and should not overlap in memory with
source.
You copy a string of size 8 ("aaabbcc" and the implicit null terminator) into your buffer of size 4. This is what referred to as a buffer overflow; you copied a string into a buffer smaller than the string requires.
strlen looks for a null terminator in the string to find the string size. It reads your buffer overflowed string which is why it returns 7: the size of your buffer overflowed string minus one for the null terminator.
Note that it may seem unimportant to allocate a buffer of the correct size, but it is critical to do so. An overflowed value could be overridden in memory or override other memory causing undefined behaviour.

Related

Question about strcpy using char pointer in C

I'm doing some programming with C, and I have a minor problem using strcpy.
char* file="It has something inside"
int size= sizeof(file);
char* file_save = malloc(sizeof(char)*size);
strcpy(file_save,file);
My code stopped working in the last line.
What can be the problem here?
It seems like something went wrong outside this part of the code. It works perfectly well if I change sizeof into strlen in the online gdb, but it still stops in the strcpy line on my computer's VS code. Thank you for helping me.
As comments suggest, the size is the size of variable char pointer which is probably 8 if you are working on a 64-bit machine. So you need the size of string the file is pointing to. You can get that like below:
int size = strlen(file) + 1;
The strlen returns the number of bytes this string has. Every string is finished by a null terminator \0. While you are writing in a file it doesn't matter which bytes are for the string and which is the null terminator so you need to count both.
The variable file has the pointer type char *
char* file="It has something inside";
It would be even better to declare the pointer with the qualifier const because you may not change the string literal pointed to by the pointer
const char *file = "It has something inside";
Its size returned by the operator sizeof
int size= sizeof(file);
does not depend on what string the pointer points to and usually is equal to 4 or 8 bytes.
As you are going to copy the pointed string literal you need to determine its length. To do this you can use standard string function strlen. It returns the number of characters in a string until the terminating zero character '\0' is encountered.
So you need to write
size_t size = strlen( file );
Now you need to allocate memory for size characters plus one for the terminating zero character '\0' of the string literal.
char* file_save = malloc( size + 1 );
So all is ready to copy the source string provided that the memory was allocated successfully.
strcpy( file_save, file );
What can be the problem here?
A pointer is not an array and not a string. An array is not a pointer. A string is not a pointer.
Below, file is a pointer.
char* file = "It has something inside";
int size = sizeof(file);
sizeof(file) is the size of a pointer, not the size of array nor the size of a string.
Later code needs to use the size of a string, not the size of a pointer.
To find the size of a string, use the pointer file, which points to a string and then call strlen().
// `length` is the string length: characters up to, but not including the null character.
size_t length = strlen(file);
// `size` is the string size: characters up to, and including the null character.
size_t size = length + 1;
Use size to determine allocation needs for a copy of the string.

memory allocation for char pointer

I am actually supposed to dynamically store a string. I have tried the below,
It is printing everything but it terminating as soon as a space is included in my input. can someone explain is why?
Also what is the right way to do it :
int i;
char *a;
a=(char *)malloc(sizeof(char));
scanf("%s",a);
for(i=0;*(arr+i)!='\0';i++)
printf("%c",*(arr+i));
It is printing everything but it terminating ...
Consider your memory allocation statements:
char *a;
a=(char *)malloc(sizeof(char));
By allocating only sizeof(char) bytes to the buffer a, then attempting to write anything more than the null terminator to it, you are invoking undefined behavior. (Note: sizeof(char) in C is by definition equal to 1, always)
C strings are defined as a null terminated character array. You have allocated only one byte. The only legal C string possible is one containing only the null termination byte. But your code attempts to write much more, and in so doing encroaches on memory locations not owned by your process. So in general, when creating strings, follow two simple rules:
Determine max length of string you need
allocate memory to max length + 1 bytes to accommodate termination byte.
Example if max string is x characters long, create the memory for x + 1 characters:
char inputStr[] = {"This string is x char long"};
char string = malloc(strlen(inputStr) +1); //+1 for null byte
strcpy(string, inputStr);
Note, in C it is not recommended to cast the return of malloc() and family.
You've two problems with your code. Firstly, you only allocate enough space for 1 character and since strings have to be NUL terminated, the longest string you could have is 0 characters long. Since you don't know how long the text you're going to read in, you could start with an arbitrary size (say 1024).
a=malloc(1024);
Secondly, scanf will only read up to the next space when you use "%s". It also isn't constrained by the available space in a. A better way to to read in an entire line of text, is to use fgets like this
fgets(a,1024,stdin);
This will read up to 1023 characters or up to and including the next newline character. It will NUL terminate the string for you as well.
You can then print it as a string.
printf("%s",a);
char *a;
/* Initial memory allocation */
a = (char *) malloc(1024); // your buffer size is 1024
// do something with a
free(a);
Copy bellow string in your variable then print the string with "%s" as string and theres no need use of "%c" :
strcpy(a, "this is a string");
printf("String = %s", a);
Dont forget using of free(), if you dont use of this then you will get memory leak problem.

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

C Noob: Define size of a char array while copying contents of char* into it

I have a basic question in C.
I need to print the contents of a char pointer. The contents are binary and therefore I use hex format to see the contents.
Would detecting a null still work?
unsigned char *input = "������";
printf("input =");
int count = 0;
while(*input != '\0'){
printf("%02x", *input);
input++;
}
printf("\n");
Now what happens if I have to copy the pointer to a char array?
How can I assign the size of the char array? I understand sizeof returns only the size of datatype that char points to. But is there any way?
unsigned char copyInput[size??];
strcpy(copyInput, input);
for (i=0, i <size?, i++)
{
printf("copyInput[%d]= %02x", i, copyInput[i]);
}
Thanks in advance!
1) To the extent that C has strings at all, they are defined as "an arbitrary contiguous sequence of nonzero bytes, terminated with a zero byte". Therefore, if your binary data is guaranteed never to contain bytes whose value is zero, you can safely treat it as a C string (use the str* functions with it, etc). But if your binary data might have zero bytes somewhere in the middle, you need to track the length separately and operate on it with the mem* functions instead.
2) You use strlen to find the length of the string (without the terminating zero byte). However, in standard C89 you can't use the result of strlen to set the size of a char[] variable, because the size has to be known at compile time. If you're using C99 or GNU extensions, you can define the size of an array at runtime:
size_t n = strlen(s1);
char s2[n+1];
memcpy(s2, s1, n);
The n+1 is necessary, or you won't have space for the terminating NUL. If you can't use C99 nor GNU extensions, your only option is to allocate space on the heap:
size_t n = strlen(s1);
char *s2 = malloc(n+1);
memcpy(s2, s1, n);
or, with a common library extension, just
char *s2 = strdup(s1);
Either way, don't forget to free(s2) later. By the way, this is a case where it would have been safe to use strcpy, because you know by construction that the destination buffer is big enough. I used memcpy because it may be slightly more efficient and it means human readers won't see "strcpy" and start worrying.
If it's a bunch of chars terminated with a 0, just use strlen() since that is C's definition of a string. It doesn't matter than some (or most) of the characters might be unprintable, as long as 0 is the terminator.
You will have problems if any of the input bytes are 0. In this case the loop will stop at that character. Otherwise, you can treat it as a string.
Treating it as a string, you can use strlen() to get the input's size and then dynamically allocate memory to your copy. The copy can be made with strcpy as you did, but it is safer to use strncpy.
char *input = "input binary array";
int count = strlen(input)+1; // plus '\0'
char *copy = (char *) malloc(count*sizeof(char));
strncpy(copy, input, count+1);

Resources