piggyback
piggyback

Reputation: 9264

Is strlen unsafe when getting the last char in a string in C

Is there a way for me to get the last char in a string with strlen? If not, I can't understand in what context strlen can be used.

char buf[256] = "Hello";
char * lastchar = buf[strlen(buf) - 1];

Is it safe to use it?

Upvotes: 0

Views: 10290

Answers (6)

Hartmut Schorrig
Hartmut Schorrig

Reputation: 549

If the buffer contains guaranteed a 0 character and at least one character, it is safe. But this condition may not met ... in development phase, on errors in other software modules (which determines the buffer), in attack of a virus, .... Access on the position [-1] if the string es empty is usual not a problem in C language but it returns a non determined result. Hence this construct is too simple and usafe. In generally strlen is unsafe: Think on a situation, the software is not ready, the buffer is not filled because this part of software has an error, and the buffer contains ..AA AA.. (for example) till end of memory. Then the strlen(..) runs a long time, maybe crash on its end (because null-Pointer or memory protection) and may violate the cycle time of an interrupt. There are some better solutions, but not really standardized. My solution you can find in www.vishia.org/emc/html/Base/StringJc_en.html resp. the whole system www.vishia.org/emc

Upvotes: 0

Chris Reid
Chris Reid

Reputation: 488

strlen is unsafe for null pointers.

char* str = (char*)NULL;
size_t len = strlen(str);  /* segmentation fault -- crash */

50 years later, this is still there, waiting to trap the unwary.

Fortunately , there is an easy remedy.

#define strlen(S) ( (S==NULL) ? 0 : strlen(S) )

will stop the seg fault and return 0 as expected.

Upvotes: 0

chux
chux

Reputation: 154169

The last char in a string is always a null character.

char lastchar = buf[strlen(buf)];

A string is a contiguous sequence of characters terminated by and including the first null character. C11 §7.1.1


To get the second to last character in a string is safe only when the string contains more than the null character.

size_t len = strlen(buf);
if (len > 0) {
  char secondtolastchar = buf[len-1];
}

Keep in mind strlen(buf) - 1 is never negative even if strlen() returns zero. What happens below?

char buf2[2] = "X";
char *buf = &buf2[1];
char ch = buf[strlen(buf) - 1];

buf takes on the address of the null character in buf2[] and strlen(buf) --> 0. So it looks like the next line of code would do buf[-1] which hopefully would be 'X'. Instead, strlen() returns type size_t which is some unsigned integer type. The subtraction of size_t and int certainly results in a size_t. So ((size_t) 0) - 1 is the largest size_t value:SIZE_MAX and not -1. Thus buf[SIZE_MAX] is outside the range of buf2[] and is undefined behavior.

Therefore for safety, any subtraction like - 1 needs to consider the effect of overflow. The above code solves that with if (len > 0)

Upvotes: 3

Iskar Jarak
Iskar Jarak

Reputation: 5325

Provided your strings are actually null-terminated (otherwise they're not actually strings!!!), yes, it is safe, so long as there is at least one character (other than the terminating null) in the string.

strlen() calculates the number of bytes in a null-terminated string, excluding the null terminator. Bear in mind that C uses 0-based indexing.

So "Hello" is really 'H', 'e', 'l', 'l', 'o', '\0', strlen("Hello") returns 5, and so you are accessing buf[4] (the 'o'), which is fine. If you had the empty string, "", there is no second last character and so here it is important to check the return value of strlen() before using it.

One caveat: If you meant to get the last character, you should have done

char lastchar = buf[strlen(buf) - 1];

and if you meant to get a pointer to the last character, you should have done

char * lastchar = &buf[strlen(buf) - 1];

Upvotes: 11

Mad Physicist
Mad Physicist

Reputation: 114488

Yes. That is one perfectly valid use, except you have to do pointer arithmetic instead of indexing: char * lastchar = buf + strlen(buf) - 1; (remember that buf is a pointer). An alternative would be to use strchr(), which may be faster: char * lastchar = strchr(buf, '\0');.

Another use of strlen() can be when you want to copy a string and you need to know how much memory to allocate:

char *copy = malloc(strlen(buf) + 1);
strcpy(copy, buf);

Upvotes: 0

Michael Albers
Michael Albers

Reputation: 3779

Assuming your string is properly null terminated (as it is in your example) it's safe.

Upvotes: 1

Related Questions