0

I am incredibly new in C programming and I'm having a hard time understanding some aspects of it, including the strcpy() function.

I am doing some quizzes and passed over the following question:

To assure the correctness of the following strcpy(d,s) call, which of the following conditions must always be met:

a. sizeof(d) >= strlen(s) + 1

b. sizeof(d) >= sizeof(s)

c. sizeof(d) >= strlen(s)

d. strlen(d) >= strlen(s)

e. strlen(d) >= strlen(s) + 1

After doing some research, I found that the size of the destination string should be large enough to store the copied string. Source here. This led me to answers either b or d.

However the correct answer is 'a' and I cannot understand why, and cannot find any documentation. Could someone please explain in more details what the restrictions of strcpy() are?

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
Elena M.
  • 3
  • 4
  • how are `d` and `s` declared, are they both static arrays or are they pointers? `sizeof` does not work the same for static and dynamic arrays (e.g `int a[20]` and `int* a`) – Chase Jun 22 '20 at 17:21
  • @Chase, unfortunately I do not have this information. This is all the information that was given to me in the question. – Elena M. Jun 22 '20 at 17:23

3 Answers3

0

All character strings in C (the kind used by functions such as strcpy) must have a nul-terminator (a zero-value char signalling the end of the string). So, to store a string like "abc", you will need any char[] array to have at least four elements: one for each of the letters plus one for the nul-terminator.

The strlen() function returns the number of characters in the given string not including that nul-terminator; but the strcpy() function copies all characters including the terminator, so the destination buffer must be at least one 'chargreater than thestrlen` of the source.

Also note that the sizeof(d) calculation will only work if d is declared as an array of char (e.g. char d[42]); if that array is passed to a function, it will 'decay' to a pointer, and the array's size will not be (implicitly) known to that function; see this discussion: How to find the 'sizeof' (a pointer pointing to an array)?.

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
0

It is copying a sequence of character bytes with a null terminator. For example the string "ABC" is represented 65,66,67,0.

strlen calculates the length of the string excluding the null terminator (e.g. 3 for "ABC"). sizeof (for an array) gives you the amount of memory set aside for the array. The string it contains may be shorter.

char s[20] = "ABC"; would give you a string of length 3, using 4 bytes including the terminator, in a reserved memory space of 20 bytes.

To safely copy from s to d, you need to have enough space in d to receive the string and its terminator (without the terminator you won't have a valid string). Hence strlen(s)+1.

The size of s is irrelevant as not all of the reserved space will be copied. strlen(d) is irrelevant also - any existing string in d will be overwritten.

So option a is correct.

wotnotv
  • 101
  • 1
0

It sort of depends on how the variables are declared and/or defined even, however judging by the fact that the answer is a, I'm positive that this is how they were declared and defined-

// Assume SIZE_0 and SIZE_1 are some integer values
char d[SIZE_0];
char s[SIZE_1];

// Assign a bunch of characters to `s` here and null terminate it
// Assume `s` now has `LEN` number of characters + 1 for the null terminator, for a total of `LEN + 1`
// Of course, `LEN + 1` is either less than, or equal to, `SIZE_1`

Now let's get the values cleared up real quick-

  • strlen(s) -> Returns LEN, as it counts the number of characters until the null terminator
  • sizeof(s) -> Returns SIZE_1
  • sizeof(d) -> Returns SIZE_0
  • strlen(d) -> Doesn't work as you'd think, strlen won't work without a null terminator, currently d has no value - so there's no length, not even 0 would count unless you set d[0] to '\0' by yourself

So, it's evident that for strcpy(d, s) to work, sizeof(d) (which is the only valid call) MUST BE more than, or equal to, LEN + 1 (LEN for all the characters from s and +1 for the null terminator).

Of course, strlen on s will return LEN, so we'll need strlen(s) + 1.

And that is why you need sizeof(d) to be more than, or equal to, strlen(s) + 1.

I must say though, if strlen did return the capacity (aka size) of the string, instead of the current length, your assumption would work.

At the end of the day, always remember the difference between capacity (size) and length, especially in C.

Chase
  • 5,315
  • 2
  • 15
  • 41
  • So we are going under the assumption that d would have no value assigned to it when strcpy(d,s) is being called? Is the null terminator mandatory when assigning values to these variables? Meaning, what if s did not have the null terminator? – Elena M. Jun 22 '20 at 17:42
  • @ElenaM. yep! because if `d` has a null terminated string assigned to it, option c would be correct as well, since then `strlen` is a valid call. – Chase Jun 22 '20 at 17:44
  • I should also mention, option B is also correct (assigned or not), but that's really pushing it as that's not the *minimum boundary* – Chase Jun 22 '20 at 17:45
  • Asking again as you might not see my edit. Is the null terminator mandatory when assigning values to these variables? Meaning, what if s did not have the null terminator? – Elena M. Jun 22 '20 at 17:46
  • @ElenaM. C strings should always be null terminated, otherwise you're going towards undefined behaviour territory, library functions like `strlen` will not work on non-null terminated strings, see [here](https://stackoverflow.com/questions/631516/strlen-on-non-null-terminated-char-string) – Chase Jun 22 '20 at 17:47
  • Alright! That really cleared things up. Thank you!!!! – Elena M. Jun 22 '20 at 17:50