I've read the function headers, but I'm still not sure what exactly the difference is in terms of use cases.
memcpy() copies from one place to another. memset() just sets all pieces of memory to the same value.
Example:
memset(str, '*', 50);
The above line sets the first 50 characters of the string str to * (or whatever second argument of the memset).
memcpy(str2, str1, 50);
The above line copies the first 50 characters of str1 to str2.
memset() sets all of the bytes in the specified buffer to the same value, memcpy() copies a sequence of bytes from another place to the buffer.
char a[4];
memset(a, 7, sizeof(char)*4);
/*
* a is now...
*
* +-+-+-+-+
* |7|7|7|7|
* +-+-+-+-+
*/
char b[] = {1,2,3,4};
char c[4];
memcpy(c, b, sizeof(char)*4);
/*
* c is now...
*
* +-+-+-+-+
* |1|2|3|4|
* +-+-+-+-+
*/
memset() is used to set all the bytes in a block of memory to a particular char value. Memset also only plays well with char as it's its initialization value.
memcpy() copies bytes between memory. This type of data being copied is irrelevant, it just makes byte-for-byte copies.
memset sets a block of memory to a single value. memcpy copies the content of a block into another block.
Perhaps you'd be interested in the difference between memcpy and memmove. Both do the same, but the latter works even if the source and destination overlap.
memset fill memory with constant byte
void *memset(void *s, int c, size_t n);
Use of memset is programmer can directly fill memory with particular.
and memcpy uses constant void pointer to source which cannot be changed.
memcpy copy the memory area
void *memcpy(void *dest, const void *src, size_t n);
Reference memcpy
memset
memcpy() copies from one place to another. memset() just sets all pieces of memory to the same.
For example here sets string length of the string str to * (or whatever second argument of the memset).
memset(str, '*', strlen(str)+1);
Here copies the string length of the string src to dest.
memcpy(dest, src, strlen(src)+1);
Related
I do not understand why do we have to return an unsigned int for strlcat and strlcpy, why do we need that ? it's not the aim of the function.
Thanks for your responses
The aim of these functions is to move strings (in some way), and a very frequent question by the programmer when you do that is "how many chars were moved?".
Since it already knows this information, it is no more work for it to return this information. Otherwise the programmer would have to do some expensive strlen()'s before and/or after.
Also, if they fail due to a too small buffer, they give you the number of characters they would need, so you can detect the truncation, and potentially reallocate the buffer.
strlcpy and strlcat are non standard functions available on some BSD versions of Unix that perform a safe version of strcpy and strcat with truncation. They do not actually return an unsigned int, but a size_t, which is the type returned by sizeof and may be different from unsigned int.
The functions are declared in <string.h> with these prototypes:
size_t strlcpy(char *dst, const char *src, size_t size);
size_t strlcat(char *dst, const char *src, size_t size);
dst is a pointer to the destination array. This array must contain a valid C string for strlcat, it can be NULL if size is 0.
src must be a valid pointer to a C string.
size is the size in bytes of the destination array.
The functions perform a string copy or concatenation, similar to strcpy and strcat, but do not write beyond the end of the destination array (size). They null terminate the destination array unless size is 0 or dst points to an array without a null terminator in the first size bytes for strlcat.
Both functions return the length in bytes of the resulting string if the destination array was long enough. This permits easy detection of truncation.
Here is an example:
char dest[10];
size_t len = strlcpy(dest, "This is a random string", sizeof dest);
if (len >= sizeof dest) {
/* Truncation occurred. You could ignore it, issue a diagnostic,
or reallocate the destination array to at least `len+1` bytes */
printf("Truncation occurred\n");
}
So here is the answer to your question: the return value is useful if the programmer wants to detect truncation, otherwise it may be safely ignored.
Synopsis of strlcpy() and strlcat()
#include <string.h>
size_t
strlcpy(char *dst, const char *src, size_t size);
size_t
strlcat(char *dst, const char *src, size_t size);
The strlcpy() and strlcat() functions return the total length of the
string they tried to create. For strlcpy() that means the length of src.
For strlcat() that means the initial length of dst plus the length of
src. While this may seem somewhat confusing it was done to make truncation detection simple.
Note however, that if strlcat() traverses size characters without finding
a NUL, the length of the string is considered to be size and the destination string will not be NUL terminated (since there was no space for the
NUL). This keeps strlcat() from running off the end of a string. In
practice this should not happen (as it means that either size is incorrect or that dst is not a proper ``C'' string). The check exists to prevent potential security problems in incorrect code.
This program reads a text file into a string array, line by line. I can't understand the meaning of two lines in the code:
char **words = (char **)malloc(sizeof(char*)*lines_allocated);
...
words = (char **)realloc(words,sizeof(char*)*new_size);
...
Please could you help me understand them?
char **words = (char **)malloc(sizeof(char*)*lines_allocated);
Allocates lines_allocated pointers. When you use pointer to pointers you need to allocate space for the pointers, and them for each of those pointers you allocate space for you data, in this case, a char *.
words = (char **)realloc(words,sizeof(char*)*new_size);
This changes the size of the buffer, as the number of lines is unknown before you read the file, then you need to increase the number of pointers you allocate.
words points to a block that will store lines_allocated pointers at first moment and then it will be increased to new_size when needed.
In your code you also have a line like this:
/* Allocate space for the next line */
words[i] = malloc(max_line_len);
Which will allocate each string separately.
Also, don't cast the result of malloc:
Do I cast the result of malloc?
The first line allocates a chunk of dynamic memory (creates space for an array of pointers to char); the second line resizes that chunk.
A better way to write both lines is
char **words = malloc( sizeof *words * lines_allocated); // no cast, operand of sizeof
char **tmp = realloc( words, sizeof *words * new_size );
if ( tmp )
words = tmp;
In C, you don't need to cast the result of either call, and it's considered bad practice to do so. Also, note the operand to sizeof; if you ever change the base type of words (from char to wchar_t, for example), you won't have to change the malloc or realloc calls.
realloc will return NULL if it can't extend the buffer, so it's safer to assign the result to a temporary variable first, otherwise you risk losing your reference to that memory, meaning you won't be able to access or release it.
The first line allocates a pointer to a pointer to character. A pointer to something in C is equivalent to a pointer to an array of that same something, so this is equivalent to saying that it allocates a pointer to an array of pointers to char.
sizeof(char*) is the size of a pointer, and multiplying it by lines_allocated means that the number of pointers in the allocated array will be lines_allocated.
The second line reallocates the array of pointers so that it may now contain new_size pointers instead of lines_allocated pointers. If new_size is larger, the new pointers will be undefined, and must be initialized before being used.
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
What form is correct in allocating string in C?
char *sample;
sample = malloc ( length * sizeof(char) );
or
sample = malloc ( length * sizeof(char*) );
Why does char* take 4 bytes when char takes 1 byte?
Assuming the goal is to store a string of length characters, the correct allocation is:
sample = malloc(length + 1);
Notes:
Don't use sizeof (char), since it's always 1 it doesn't add any value.
Remember the terminator, I assumed (based on name) that length is the length in visible characters of the string, i.e. the return of strlen() will be length.
I know you didn't, but it's worth pointing out that there should be no cast of the return value from malloc(), either.
The reason char * is larger is that it's a pointer type, and pointers are almost always larger than a single character. On many systems (such as yours, it seems) they are 32 bit, while characters are just 8 bits. The larger size is needed since the pointer needs to be able to represent any address in the machine's memory. On 64-bit computers, pointers are often 64 bits, i.e. 8 characters.
Why does char* take 4 bytes when char takes 1 byte?
Because you are on a 32-bit systems, meaning that pointers take four bytes; char* is a pointer.
char always takes exactly one byte, so you do not need to multiply by sizeof(char):
sample = malloc (length);
I am assuming that length is already padded for null termination.
sample = malloc ( length * sizeof(char) );
First is the correct one if you want to allocate memory for length number of characters.
char* is of type pointer which happens to be 4 bytes on your platform. So sizeof(char*) returns 4.
But sizeof(char) is always 1 and smae is guaranteed by the C standard.
In the given cases you are doing two different things:
In the first case : sample = malloc ( length * sizeof(char) );
You are allocating length multiplied by the size of type char which is 1 byte
While in the second case : sample = malloc ( length * sizeof(char*) );
You are allocating length multiplied by the size of pointer to char which is 4 byte
on your machine.
Consider that while case 1 remains immutable, on the second case the size is variable.
sample = malloc(length);
is the right one
char* is a pointer, a pointer uses 4 bytes (say on a 32-bit platform)
char is a char, a char uses 1 byte
In your case, you want to alloc an array of length characters. You will store in sample a pointer to an array of length times the size of what you point to. The sizeof(char*) is the size of a pointer to char. Not the size of a char.
A good practice is
sample = malloc(length * sizeof(*sample));
Using that, you will reserve length time the size of what you want to point to. This gives you the ability to change the data type anytime, simply declaring sample to be another kind of data.
int *sample;
sample = malloc(length * sizeof(*sample)); // length * 4
char *sample;
sample = malloc(length * sizeof(*sample)); // length * 1
Provided the length already accounts for the nul terminator, I would write either:
sample = malloc(length);
or:
sample = malloc(length * sizeof(*sample));
sizeof(char*) is the size of the pointer, and it is completely irrelevant to the the size that the allocated buffer needs to be. So definitely don't use that.
My first snippet is IMO good enough for string-manipulation code. C programmers know that memory and string lengths in C are both measured in multiples of sizeof(char). There's no real need to put a conversion factor in there that everybody knows is always 1.
My second snippet is the One True Way to write allocations in general. So if you want all your allocations to look consistent, then string allocations should use it too. I can think of two possible reasons to make all your allocations look consistent (both fairly weak IMO, but not actually wrong):
some people will find it easier to read them that way, only one visual pattern to recognise.
you might want to use the code in future as the basis for code that handles wide strings, and a consistent form would remind you to get the allocation right when the length is no longer measured in bytes but in wide chars. Using sizeof(*sample) as the consistent form means you don't need to change that line of code at all, assuming that you update the type of sample at the same time as the units in which length is measured.
Other options include:
sample = calloc(length, 1);
sample = calloc(length, sizeof(char));
sample = calloc(length, sizeof(*sample));
They're probably fairly pointless here, but as well as the trifling secondary effect of zeroing the memory, calloc has an interesting difference from malloc that it explicitly separates the number and size of objects that you're planning to use, whereas malloc just wants the total size.
For any type T, the usual form is
T *p = malloc(N * sizeof *p);
or
T *p;
...
p = malloc(N * sizeof *p);
where N is the number of elements of type T you wish to allocate. The expression *p has type T, so sizeof *p is equivalent to sizeof (T).
Note that sizeof is an operator like & or *, not a library function; parentheses are only necessary if the operand is a type name like int or char *.
Please visit this Linkhttps://www.codesdope.com/c-dynamic-memory/for understand how it allocat the memory dynamically at run time. It might be helpful to understand the concept of malloc and how it allocate the amount of memory to the variable.
In your example;
char *sample;
sample = malloc ( length * sizeof(char) );
here, you are declare a pointer to character for sample without declaring how much memory it required. In the next line, length * sizeof(char) bytes memory is assigned for the address of sample and (char*) is to typecast the pointer returned by the malloc to character.
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);