Just curious to know (as we use these functions often). I don't see any practical difference between strncpy() and memcpy(). Isn't it worth to say that effectively,
char* strncpy (char *dst, const char *src, size_t size)
{
return (char*)memcpy(dst, src, size);
}
Or am I missing any side effect? There is one similar earlier question, but couldn't find an exact answer.
There is a difference, see this part of the strncpy page you linked to (emphasis mine):
Copies the first num characters of source to destination. If the end of the source C string (which is signaled by a null-character) is found before num characters have been copied, destination is padded with zeros until a total of num characters have been written to it.
So if the string to be copied is shorter than the limit, strncpy pads with zero while memcpy reads beyond the limit (possibly invoking undefined behaviour).
No, they are not the same.
From the C Standard (ISO/IEC 9899:1999 (E))
7.21.2.3 The strcpy function
Description
2 The strncpy function copies not more than n characters (characters that follow a null
character are not copied) from the array pointed to by s2 to the array pointed to by s1.260) If copying takes place between objects that overlap, the behavior is undefined.
3 If the array pointed to by s2 is a string that is shorter than n characters, null characters are appended to the copy in the array pointed to by s1, until n characters in all have been written.
Returns
4 The strncpy function returns the value of s1.
7.21.2.1 The memcpy function
Description
2 The memcpy function copies n characters from the object pointed to by s2 into the object pointed to by s1. If copying takes place between objects that overlap, the behavior is undefined.
Returns
3 The memcpy function returns the value of s1.
when using memcpy() the source and destination buffers can overlap, while in strncpy() this must not happen.
According to the C standard, the behavior for overlapping buffers are undefined for both strncpy() and memcpy().
According to the C standard, the real difference between strncpy() and memcpy() is that if the source string is less then N value, then NULL characters are appended to the remaining N quantity.
memcpy() is more efficient, but less safe, since it doesn't check the source to see if it has N quantity to move to the target buffer.
No, strncpy() is not a specialization, since it will detect a '\0' character during the copy and stop, something memcpy() will not do.
Adding on to what the others have said, the type of the src and dst pointers does not matter. That is, I can copy a 4 byte integer to 4 consecutive characters of 1 byte like this:
int num = 5;
char arr[4];
memcpy(arr, &num, 4);
Another difference is that memcpy does not look ofr any characters (such as NULL, by strncpy). It blindly copies num bytes from source to destination.
Edited: Properly formatted the code
You could potentially make strncpy faster by checking for a \0 and not copying past that point. So memcpy would always copy all the data, but strncpy would often be faster because of the check.
Related
Given alignas(N) char buffer[N]; and a char* p between [&buffer[0], &buffer[N-1]], can I obtain a pointer to buffer[0] by using p and N?
char* previous_aligned_pointer(char* ptr, size_t align) {
// how?
}
int main() {
constexpr int N = 32;
alignas(N) char buffer[N];
assert(previous_aligned_pointer(&buffer[rand() % N], N) == &buffer[0]);
}
I'd like to do it in portable C++ (if possible), so something like casting a pointer to uintptr_t and then performing arithmetic on it may not be used.
There is a standard library function to get the next aligned pointer. It's called std::align. You could then subtract the alignment to get the previous one.
In general that may do pointer arithmetic beyond the buffer in which case the subtraction would technically be UB. If that's a concern, then you could avoid the UB if you can allocate extra space in the buffer such that the next aligned pointer is always within the buffer.
Only other way is to implement it yourself which would have to rely on conversion to integer type which relies on implementation dependent unguaranteed behaviour. In conclusion: No, I don't think there's a general strictly standard conforming solution.
However, for your example case, there's no problem. The next aligned address is pointer past the end, so it's fine to subtract N to get the address to beginning of the buffer.
I was recently faced with a line of code and four options:
char fullName[30] = {NULL};
A) First element is assigned a NULL character.
B) Every element of the array is assigned 0 ( Zeroes )
C) Every element of the array is assigned NULL
D) The array is empty.
The answer we selected was option C, as, while the array is only initialized with a single NULL, C++ populates the rest of the array with NULL.
However, our professor disagreed, stating that the answer is A, he said:
So the very first element is NULL, and when you display it, it's displaying the first element, which is NULL.
The quote shows the question in its entirety; there was no other information provided. I'm curious to which one is correct, and if someone could explain why said answer would be correct.
The question is ill-defined, but Option B seems like the most correct answer.
The result depends on how exactly NULL is defined, which depends on the compiler (more precisely, on the standard library implementation). If it's defined as nullptr, the code will not compile. (I don't think any major implementation does that, but still.)
Assuming NULL is not defined as nullptr, then it must be defined as an integer literal with value 0 (which is 0, or 0L, or something similar), which makes your code equivalent to char fullName[30] = {0};.
This fills the array with zeroes, so Option B is the right answer.
In general, when you initialize an array with a brace-enclosed list, every element is initialized with something. If you provide fewer initializers than the number of elements, the remaining elements are zeroed.
Regarding the remaining options:
Option C is unclear, because if the code compiles, then NULL is equivalent to 0, so option C can be considered equivalent to Option B.
Option A can be valid depending on how you interpret it. If it means than the remaining elements are uninitialized, then it's wrong. If it doesn't specify what happens to the remaining elements, then it's a valid answer.
Option D is outright wrong, because arrays can't be "empty".
char fullName[30] = {NULL};
This is something that should never be written.
NULL is a macro that expands to a null pointer constant. A character - not a pointer - is being initialised here, so it makes no sense to use NULL.
It just so happens that some null pointer constants are also integer literals with value 0 (i.e. 0 or 0L for example), and if NULL expands to such literal, then the shown program is technically well-formed despite the abuse of NULL. What the macro expands to exactly is defined by the language implementation.
If NULLinstead expands to a null pointer constant that is not an integer literal such as nullptr - which is entirely possible - then the program is ill-formed.
NULL shouldn't be written in C++ at all, even to initialise pointers. It exists for backwards compatibility with C to make it easier to port C programs to C++.
Now, let us assume that NULL happens to expand to an integer literal on this particular implementation of C++.
Nothing in the example is assigned. Assignment is something that is done to pre-existing object. Here, and array is being initialised.
The first element of the array is initialised with the zero literal. The rest of the elements are value initialised. Both result in the null character. As such, the entire array will be filled with null characters.
A simple and correct way to write the same is:
char fullName[30] = {};
B and C are equally close to being correct, except for wording regarding "assignment". They fail to mention value initialisation, but at least the outcome is the same. A is not wrong either, although it is not as complete because it fails to describe how the rest of the elements are initialised.
If "empty" is interpreted as "contains no elements", then D is incorrect because the array contains 30 elements. If it is interpreted as "contains the empty string", then D would be a correct answer.
You are almost correct.
The professor is incorrect. It is true that display finishes at the first NULL (when some approaches are used), but that says nothing about the values of the remainder of the array, which could be trivially examined regardless.
[dcl.init/17.5]:: [..] the
ith array element is copy-initialized with xi for each 1 ≤ i ≤ k, and value-initialized for each k < i ≤ n. [..]
However, none of the options is strictly correct and well-worded.
What happens is that NULL is used to initialise the first element, and the other elements are zero-initialised. The end result is effectively Option B.
Thing is, if NULL were defined as an expression of type std::nullptr_t on your platform (which it isn't, but it is permitted to be), the example won't even compile!
NULL is a pointer, not a number. Historically it has been possible to mix and match the two things to some degree, but C++ has tried to tighten that up in recent years, and you should avoid blurring the line.
A better approach is:
char fullName[30] = {};
And the best approach is:
std::string fullName;
Apparently, Your Professor is right, let's see how
char someName[6] = "SAAD";
how the string name is represented in memory:
0 1 2 3 4 5
S A A D
Array-based C string
The individual characters that make up the string are stored in the elements of the array. The string is terminated by a null character. Array elements after the null character are not part of the string, and their contents are irrelevant.
A "null string" is a string with a null character as its first character:
0 1 2 3 4 5
/0
Null C string
The length of a null string is 0.
In the C++ reference of c_str() in std::string the following appears:
Return value
Pointer to the underlying character storage.
data()[i] == operator[](i) for every i in [0, size()) (until C++11)
data() + i == &operator[](i) for every i in [0, size()] (since C++11)
I do not understand the difference between the two, except for the range increase by one element since C++11.
Isn't the former statement data()[i] == operator[](i) also true for the latter?
Except for the range increment by one element since C++11, there is still a big difference between:
data()[i] == operator[](i)
and:
data() + i == &operator[](i)
That main difference is the & operator in the prototypes.
The old prototype, allowed for copy to be made when a write operation would occur, since the pointer returned could point to another buffer than the one holding the original string.
The other difference in the prototypes between data()[i] and data() + i, is not critical, since they are equivalent.
A difference between C++ and C++11 is that in the former, an std::string was not specified explicitly by the standard for whether it would have a null terminator or not. In the latter however, this is specified.
In other words: Will std::string always be null-terminated in C++11? Yes.
Note the closing bracket difference:
[0, size())
[0, size()]
First stands for exclusive range (that is item at size index is not included) while second stands for inclusive range (that is item at size index is included)
Before C++ the precense of terminating null was not handled in this case, while in C++11 accessing character at size() position is well-defined.
As for difference between data()[i] == operator[](i) and data() + i == &operator[](i) the second one applies more restrictions on potential implementation. In first case a pointer to buffer returned by data() may be different from the pointer to buffer where a value the reference to which returned by operator [] is stored. This could happen when a new buffer was created after invocation of non-const-qualified operator[] of copied string.
Prior to C++11, it was unspecified whether the string data was null-terminated or not. C++11 says it must be null-terminated.
This question already has answers here:
Can I call memcpy() and memmove() with "number of bytes" set to zero?
(2 answers)
Closed 7 years ago.
Is there a problem in passing 0 to memcpy():
memcpy(dest, src, 0)
Note that in my code I am using a variable instead of 0, which can sometimes evaluate to 0.
As one might expect from a sane interface, zero is a valid size, and results in nothing happening. It's specifically allowed by the specification of the various string handling functions (including memcpy) in C99 7.21.1/2:
Where an argument declared as size_t n specifies the length of the array for a function, n can have the value zero on a call to that function. [...] On such a call, a function that locates a character finds no occurrence, a function that compares two character sequences returns zero, and a function that copies characters copies zero characters.
Yes, it's totally Ok. The only restriction on memcpy is that memory areas must not overlap.
strlen() is a function argument should be a string but why is it also applicable to character arays ?
For eg
char abc[100];
cin.getline(abc,100);
len=strlen(abc);
If it works for character array and tells the number of elements , can it be used for int array also?
Note : I am using TurboC++
It's important to understand what a string is. The C standard defines a string as "a contiguous sequence of characters terminated by and including the first null character". It's a data format, not a data type; a C-style string may be contained in an array of char. This is not to be confused with the C++-specific type std::string, defined in the <string> (note: no .h suffix) header.
The <string.h> header, or preferably the <cstring> header, is incorporated into C++ from the C standard library. The functions declared in that header operate on C-style strings, or on pointers to them.
The argument to strlen is of type char*, a pointer to a character. (It's actually const char*, meaning that strlen promises not to modify whatever it points to.)
An array expression is, in most contexts, implicitly converted to a pointer to the initial element of the array. (See section 6 of the comp.lang.c FAQ for the details.)
The char* argument that you pass to strlen must point to the initial element of an array of characters, and there must be a null character ('\0') somewhere in the array to mark the end of the string. It computes the number of characters up to, but not including, the null terminator.
It does not (and cannot) compute the number of elements in an array, only the number of characters in a string -- which it can do only if the array actually contains a valid string. If there is no null character anywhere in the array, or if the pointer is null or otherwise invalid, the behavior is undefined.
So when you write:
char abc[100];
cin.getline(abc,100);
len=strlen(abc);
the call to cin.getline ensures that the array abc contains a properly null-terminated string. strlen(abc) calls strlen, passing it the address of the initial character; it's equivalent to strlen(&abc[0]).
No, strlen will not work on an array of int. For one thing, that would pass an int* value, which doesn't match the char* that strlen requires, so it probably wouldn't compile. Even ignoring that, strlen counts characters, not ints. (You can write your own similar function that counts ints if you like, but it still has to have some way to find the end of the elements that you're interested in counting. It doesn't have access to the actual length of the array unless you pass it explicitly.)
strlen only works for null-terminated char arrays.
If there's no null character at the end of the string1, calling strlen causes undefined behavior.
std::cin.getline automatically appends the null character at the end so that's why your strlen worked.
1 (which is not necessarily the same as the end of the array)
In C strings are arrays of char. All strlen does is count the number of items until a 0 (or null character) is found