What happens behind the scenes when I write: char str[80];?
I notice that I can now set str = "hello"; and also str = "hello world"; right afterwards. First time strlen(str) is 5, and second time it is 11;
But why? I thought that after str = "hello";, the char at index 5 becomes null (str[5] becomes '\0'). Doesn't that mean that str's size is now 6 and I shouldn't be able to set it to "hello world"?
And if not, then how does strlen and sizeof calculate the correct values every time?
I think you're getting confused between two different concepts: the allocated length of the array (how much total space is available), and the logical length of the string (how much space is being used).
When you write char str[80], you're getting storage space for 80 characters. You might not end up using all of that space, but regardless of what string you try storing in it, you're always going to have 80 slots into which you can place characters.
If you store the string "hello" into str, then the first six characters of str will be set to h, e, l, l, o, and a null terminating character. This doesn't change the allocated length, though - you still have 74 other slots that you can work with. If you then change it to "hello, world", you're using an extra seven characters, which fits just fine because you easily have enough allocated space to hold things. You've just changed the logical length, how much of that space is being used for meaningful data, but not the allocated length, how much space there is available.
Think of it this way. When you say char str[80], you're buying a plot of land that's, say, 80 acres. If you then put "hello" into it, you're using six acres of that available 80 acres. The rest of the land is still yours - you can build whatever you'd like there - so if you decide to tear everything down and build a longer string that uses up more acres of land, that's fine. No one is going to object.
The strlen function gives back the logical length of the string - how many characters are in the string that you're storing. It works by counting up characters until it finds a null terminator indicating the logical end of the string. The sizeof operator returns the allocated length of the array, how many slots you have. It works at compile-time and doesn't care what the array contents are.
When you declare a variable as char str[80], space for an 80 character array is allocated on the stack. This memory will be automatically released when that particular stack frame is out of scope.
When you assign it to the string literal "hello", it is copying each character into the array, then putting a null terminator at the end of the string (str[5] == '\0'). String length and array size are two different things, which is why you can reassign it to "hello world". String length is simply how many consecutive characters there are before the null terminator. If you instead declared str as char str[5], you would indeed cause a crash when you tried to reassign it to "hello world". It may be helpful to view a simple implementation of strlen:
size_t strlen(const char *str)
{
size_t return_val = 0;
while (str[return_val] != '\0') return_val++;
return return_val;
}
Of course, if there is no null terminating character, the above naive implementation will crash.
I am assuming that you are working in C. When you compile "char str[80];" basically a 80 character long space is allocated for you. sizeof(str) should always tell you that it is an 80 byte long chunk of memory. strlen(str) will count the non-zero characters starting at str[0]. This is why "Hello" is 5 and "Hello world".
I would suggest that you learn to use functions like strnlen, strncpy, strncmp, snprintf ..., this way you can prevent reading/writing beyond the end the array, for example: strnlen(str,sizeof(str)).
Also start working through online tutorials and find an introductory C/C++ book to learn from.
When you declare an array like char str[80]; 80 chars of space are reserved on the stack for you, but they are not initialized - they get whatever was already in memory at the time. It's your job as the programmer to initialize the array.
strlen does something along these lines:
int strlen(char *s)
{
int len = 0;
while(*s++) len++;
return len;
}
In other words, it returns the length of a null-terminated string in a character array, even if the length is less than the size of the total array.
sizeof returns the size of a type or expression. If your array is 80 chars long, and a char is a byte long, it will return 80, even if none of the values in the array have been initialized. If you had an array of 5 ints, and an int was 4 bytes long, sizeof would produce 20.
Related
Relatively new C programmer here. I am reviewing the following code for a tutorial for a side project I am working on to practice C. The point of the abuf struct is to create a string that can be appended to. Here is the code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct abuf {
char* str;
unsigned int size;
} abuf;
void abAppend(abuf *ab, const char *s, int len) {
char *new = realloc(ab->str, ab->size + len);
if (new == NULL) return;
memcpy(&new[ab->size], s, len);
ab->str = new;
ab->size += len;
}
int main(void) {
abuf ab = {
NULL,
0
};
char *s = "Hello";
abAppend(&ab, s, 5);
abAppend(&ab, ", world", 7);
return 0;
}
Everything compiles and my tests (redacted for simplicity) show that the string "Hello" is stored in ab's str pointer, and then "Hello, world" after the second call to abAppend. However, something about this code confuses me. On the initial call to abAppend, the str pointer is null, so realloc, according to its man page, should behave like malloc and allocate 5 bytes of space to store the string. But the string "Hello" also contains the terminating null byte, \0. This should be the sixth and final byte of the string, if I understand this correctly. Isn't this null byte lost if we store "Hello\0" in a malloc-ed container large enough only to store "Hello"?
On the second call to abAppend, we concatenate ", world" to str. The realloc will enlarge str to 12 bytes, but the 13th byte, \0, is not accounted for. And yet, everything works, and if I test for the null byte with a loop like for (int i = 0; ab.str[i] != '\0'; i++), the loop works fine and increments i 12 times (0 thru 11), and stops, meaning it encountered the null byte on the 13th iteration. What I don't get is why does it encounter the null byte, if we don't allocate space for it?
I tried to break this code by doing weird combinations of strings, to no avail. I also tried to allocate an extra byte in each call to abAppend and changed the function a little to account for the extra space, and it performed the exact same as this version. How the null byte gets processed is eluding me.
How does realloc treat null bytes in strings?
The behavior of realloc is not affected by the contents of the memory it manages.
But the string "Hello" also contains the terminating null byte, \0. This should be the sixth and final byte of the string,…
The characters are copied with memcpy(&new[ab->size], s, len);, where len is 5. memcpy copies characters without regard to whether there is a terminating null byte. Given length of 5, it copies 5 bytes. It does not append a terminating null character to those.
The realloc will enlarge str to 12 bytes, but the 13th byte, \0, is not accounted for.
On the second called to abAppend, 7 more bytes are copied with memcpy, after the first 5 bytes. memcpy is given a length of 7 and copies only 7 bytes.
… it encountered the null byte on the 13th iteration.
When you tested ab.str[12], you exceeded the rules for which the C standard defines the behavior. ab.str[12] is outside the allocated memory. It is possible it contained a null byte solely because nothing else in your process had used that memory for another purpose, and that is why your loop stopped. If you attempted this in the middle of a larger program that had done previous work, that byte might have contained a different value, and your test might have gone awry in a variety of ways.
You're correct that you only initially allocated space for the characters in the string "Hello" but not the terminating null byte, and that the second call only added enough bytes for the characters in tge string ", world" with no null terminating byte.
So what you have is an array of characters but not a string since it's not null terminated. If you then attempt to read past the allocated bytes, you trigger undefined behavior, and one of the ways UB can manifest itself is that things appear to work properly.
So you got "lucky" that things happened to work as if you allocated space for the null byte and set it.
I actually have a question regarding the concept of a char array, especially the one which is declared and initialized like below.
char aString[10] = "";
What i was taught was that this array can store up to 10 characters (index 0-9) and that at index 10 there is an automatically placed null terminating character (i know that accessing it would not be right) such that if we use string handling functions (printf, scanf, strcmp, etc.) they would know when the string stops.
However when I tried making a struct data type like below,
typedef struct customer{
char accountNum[10];
char name[100];
char idNum[15];
char address[200];
char dateOfBirth[10];
unsigned long long int balance;
char dateOpening[10];
}CUSTOMER;
inserted 10 characters into accountNum (any method, e.g. scanf), and printf it, what is printed out will be accountNum and values in the first word of name (i know that printf will stop at a space or a '\0'). This indicates that a char array does not have a terminating null at the end of the array.
Does this mean that if we have a char array of size 10 (char aString[10]), its maximum number of char it can store is 9 characters? or does things work differently in a struct? It would be nice if someone can help me the concept because it seems like i may have been working with undefined behaviour this whole time.
char aString[10] = "";
What i was taught was that this array can store up to 10 characters (index 0-9)
Yes.
and that at index 10 there is an automatically placed null terminating character
That is wrong. For one thing, index 10 would be out of bounds of the array. The compiler will certainly not initialize data outside of the memory it has reserved for the array.
What actually happens is that the compiler will copy the entire string literal including the null-terminator into the array, and if there are any remaining elements then they will be set to zeros. If the string literal is longer than the array can hold, the compile will simply fail.
In your example, the string literal has a length of 1 char (the null terminator), so the entire array ends up initialized with zeros.
i know that accessing it would not be right
There is no problem with accessing the null terminator, as long as it is inside the bounds of the array.
such that if we use string handling functions (printf, scanf, strcmp, etc.) they would know when the string stops.
Yes, they expect C-style strings and so will look for a null terminator - unless they are explicitly told the actual string length, ie by using a precision modifier for %s, or using strncmp(), etc.
However when I tried making a struct data type like below,
<snip>
inserted 10 characters into accountNum (any method, e.g. scanf), and printf it, what is printed out will be accountNum and values in the first word of name
That means you either forgot to null-terminate accountNum, or you likely overflowed it by writing too many characters into it. For instance, that is very easy to do when misusing scanf(), strcpy(), etc.
i know that printf will stop at a space or a '\0'
printf() does not stop on a space, only on a null terminator. Unless you tell it the max length explicitly, eg:
CUSTOMER c;
strncpy(c.accountNum, "1234567890", 10); // <-- will not be null terminated!
printf("%.10s", c.accountNum); // <-- stops after printing 10 chars!
If it has not encountered a null terminator by the time it reaches the 10th character, it will stop itself.
This indicates that a char array does not have a terminating null at the end of the array.
An array is just an array, there is no terminator, only a size. If you want to treat a character array as a C-style string, then you are responsible for making sure the array contains a nul character in it. But that is just semantics of the character data, the compiler will not do anything to ensure that behavior for you (except for in the one case of initializing a character array with a string literal).
Does this mean that if we have a char array of size 10 (char aString[10]), its maximum number of char it can store is 9 characters?
Its maximum storage will always be 10 chars, period. But if you want to treat the array as a C-style string, then one of those chars must be a nul.
or does things work differently in a struct?
No. Where an array is used does not matter. The compiler treats all array the same, regardless of context (except for the one special case of initializing a character array with a string literal).
What i was taught was that this array can store up to 10 characters (index 0-9) and that at index 10 there is an automatically placed null terminating character (i know that accessing it would not be right) such that if we use string handling functions (printf, scanf, strcmp, etc.) they would know when the string stops.
Yes, but accessing the null terminating character is absolutely safe.
inserted 10 characters into accountNum (any method, e.g. scanf), and printf it, what is printed out will be accountNum and values in the first word of name (i know that printf will stop at a space or a '\0'). This indicates that a char array does not have a terminating null at the end of the array.
printf does not stop for a space, only for a null terminating character. In this case, printf will print all characters until it sees '\0'.
Does this mean that if we have a char array of size 10 (char aString[10]), its maximum number of char it can store is 9 characters?
Yes.
or does things work differently in a struct?
There is no difference.
Consider this code snippet (simplified syntax for clarity).
void simple (char *bar) {
char MyArray[12];
strcpy(MyArray, bar);
}
My instructor says that MyArray can copy at most 12 elements from bar, but from what I've read, MyArray can only store 11 characters because it needs room for the null character at the end. So if the received value of bar is 12 or greater, a buffer overflow would occur. My instructor says that this will only happen if the received value of bar
is 13 or greater. Who's right? I'd appreciate if you could cite a credible source so I can convince him.
The definition char MyArray[12] creates an array of 12 char, which can be used to store a string. Since strings in C are null terminated, one of those characters needs to be able to store the null byte at the end of the string.
So a variable of type char [12] can hold a string of at most 11 characters. Attempting to copy a string of length 12 or longer using strcpy as in your example will overflow the bounds of the array.
If you were to use strncpy as follows:
strncpy(MyArray, bar, 12);
This will not overflow the buffer, as it would copy at most 12 characters. However, if 12 characters are copied, that means the string is not null terminated and is therefore not technically a string. Then attempting to use any other string function on MyArray that expect a null terminated string would read off the end of the array.
The/a proper use of strncpy would be:
void simple(char *bar) {
char MyArray[12];
strncpy(MyArray, bar, sizeof(MyArray)-1);
MyArray[sizeof(MyArray)-1]= '\0';
}
This just puts in a terminating null character, whether strncpy was able to do that or not.
It's hard to tell, because your question is a bit confusingly worded, but I think you're right, and that your instructor is wrong.
Given the code
void simple(char *bar) {
char MyArray[12];
strcpy(MyArray, bar);
}
if the passed-in bar points to a string of 11 or fewer characters, a valid string will be copied to MyArray, with no buffer overflow. But if the string is 12 (or more) characters long, you're right, there'll be a buffer overflow, because strcpy will also copy the 13th, terminating null character.
Earlier you asked about strncpy. Given the code
void simple2(char *bar) {
char MyArray[12];
strncpy(MyArray, bar, 12);
}
if the passed-in bar points to a string of 11 or fewer characters, a valid string will be copied to MyArray. But if the string is 12 characters long, we have a different problem. strncpy will copy 12 characters and stop, meaning that it won't copy the terminating null character. There won't be a buffer overflow, but MyArray still won't end up containing a valid string.
Also, you asked for a credible source. I wrote the C FAQ list -- would you consider that credible? :-)
My instructor says that MyArray can copy at most 12 elements from bar
It will be more correctly to say that the array MyArray may accomodate at most 12 elements of the array bar. Otherwise there will be an attempt to access memory beyond the array.
So in fact your instructor is right.
The array MyArray is declared having only 12 elements
char MyArray[12];
but from what I've read, MyArray can only store 11 characters because
it needs room for the null character at the end
The terminating zero is also a character. And the function strcpy copies all characters from the source string including the terminating zero that is present in the source string.
So if the received value of bar is 12 or greater, a buffer overflow
would occur
What does mean the magic number 12 in this context? is it the number of characters in the array bar or it is the length of the string stored in the array bar (that used as an argument is converted to pointer to its first element)?
If the number 12 means the size of the string stored in the array bar then the function strcpy will try to copy all characters of the array including the terminating zero and in this case the array MyArray has to be declared as having 13 elements.
char MyArray[13];
However if the number 12 means the number of elements in the array bar (used as an argument of the function) and it contains a string then the length of the string is evidently is less than 12. So the array MyArray can accept all characters of the source array including the terminating zero.
So the reason for the confusion is that you did not make a common conclusion what the number 12 means whether it is the length of the source string or it is the size of the source array.
In the first case there will be indeed undefined behavior.
In the second case if the source array contains a string then the code will be well-formed.
A char array and string are similar, but not the same.
In C,
A string is a contiguous sequence of characters terminated by and including the first null character. C11dr §7.1.1 1
void simple (char *bar) {
char MyArray[12];
strcpy(MyArray, bar);
}
My instructor says that MyArray can copy at most 12 elements from bar,
This is correct: MyArray[] can receive up to 12 characters.
strcpy() copies the memory, starting at bar to the array MyArray[] and continues until it copies a null character. If more that 12 characters (the count of 12 includes the null character) are attempted to be copied, the result is undefined behavior (UB).
MyArray can only store 11 characters
Not quite. MyArray[] can store 12 characters. To treat that data as a string, a null character must be one of those 12. When interpreted as a string, the string include all the characters up to the null character. It also include the null chracter. Each element of MyArray[] could be an 'x', but then that memory would not be a string as it lacks a null character.
So if the received value of bar is 12 or greater, a buffer overflow would occur.
Not quite. If the strcpy() attempts to write outside MyArray[], the result is undefined. Buffer overflow may occur. The program may stop, etc. The result is not defined. It is undefined behavior.
My instructor says that this will only happen if the received value of bar is 13 or greater.
bar is a pointer - it likely does not have a "value of 13". bar likely points to memory that is a string. A string includes its terminating null character, so the string may consists of 12 non-null characters and a final null character for a total of 13 characters. MyArray[] is insufficient to store a copy of that string.
Who's right?
I suspect the dis-connect is in the imprecise meaning of "bar is 13"`. I see nothing the reported by the instructor as incorrect.
I am new to C and I am very much confused with the C strings. Following are my questions.
Finding last character from a string
How can I find out the last character from a string? I came with something like,
char *str = "hello";
printf("%c", str[strlen(str) - 1]);
return 0;
Is this the way to go? I somehow think that, this is not the correct way because strlen has to iterate over the characters to get the length. So this operation will have a O(n) complexity.
Converting char to char*
I have a string and need to append a char to it. How can i do that? strcat accepts only char*. I tried the following,
char delimiter = ',';
char text[6];
strcpy(text, "hello");
strcat(text, delimiter);
Using strcat with variables that has local scope
Please consider the following code,
void foo(char *output)
{
char *delimiter = ',';
strcpy(output, "hello");
strcat(output, delimiter);
}
In the above code,delimiter is a local variable which gets destroyed after foo returned. Is it OK to append it to variable output?
How strcat handles null terminating character?
If I am concatenating two null terminated strings, will strcat append two null terminating characters to the resultant string?
Is there a good beginner level article which explains how strings work in C and how can I perform the usual string manipulations?
Any help would be great!
Last character: your approach is correct. If you will need to do this a lot on large strings, your data structure containing strings should store lengths with them. If not, it doesn't matter that it's O(n).
Appending a character: you have several bugs. For one thing, your buffer is too small to hold another character. As for how to call strcat, you can either put the character in a string (an array with 2 entries, the second being 0), or you can just manually use the length to write the character to the end.
Your worry about 2 nul terminators is unfounded. While it occupies memory contiguous with the string and is necessary, the nul byte at the end is NOT "part of the string" in the sense of length, etc. It's purely a marker of the end. strcat will overwrite the old nul and put a new one at the very end, after the concatenated string. Again, you need to make sure your buffer is large enough before you call strcat!
O(n) is the best you can do, because of the way C strings work.
char delimiter[] = ",";. This makes delimiter a character array holding a comma and a NUL Also, text needs to have length 7. hello is 5, then you have the comma, and a NUL.
If you define delimiter correctly, that's fine (as is, you're assigning a character to a pointer, which is wrong). The contents of output won't depend on delimiter later on.
It will overwrite the first NUL.
You're on the right track. I highly recommend you read K&R C 2nd Edition. It will help you with strings, pointers, and more. And don't forget man pages and documentation. They will answer questions like the one on strcat quite clearly. Two good sites are The Open Group and cplusplus.com.
A "C string" is in reality a simple array of chars, with str[0] containing the first character, str[1] the second and so on. After the last character, the array contains one more element, which holds a zero. This zero by convention signifies the end of the string. For example, those two lines are equivalent:
char str[] = "foo"; //str is 4 bytes
char str[] = {'f', 'o', 'o', 0};
And now for your questions:
Finding last character from a string
Your way is the right one. There is no faster way to know where the string ends than scanning through it to find the final zero.
Converting char to char*
As said before, a "string" is simply an array of chars, with a zero terminator added to the end. So if you want a string of one character, you declare an array of two chars - your character and the final zero, like this:
char str[2];
str[0] = ',';
str[1] = 0;
Or simply:
char str[2] = {',', 0};
Using strcat with variables that has local scope
strcat() simply copies the contents of the source array to the destination array, at the offset of the null character in the destination array. So it is irrelevant what happens to the source after the operation. But you DO need to worry if the destination array is big enough to hold the data - otherwise strcat() will overwrite whatever data sits in memory right after the array! The needed size is strlen(str1) + strlen(str2) + 1.
How strcat handles null terminating character?
The final zero is expected to terminate both input strings, and is appended to the output string.
Finding last character from a string
I propose a thought experiment: if it were generally possible to find the last character
of a string in better than O(n) time, then could you not also implement strlen
in better than O(n) time?
Converting char to char*
You temporarily can store the char in an array-of-char, and that will decay into
a pointer-to-char:
char delimiterBuf[2] = "";
delimiterBuf[0] = delimiter;
...
strcat(text, delimiterBuf);
If you're just using character literals, though, you can simply use string literals instead.
Using strcat with variables that has local scope
The variable itself isn't referenced outside the scope. When the function returns,
that local variable has already been evaluated and its contents have already been
copied.
How strcat handles null terminating character?
"Strings" in a C are NUL-terminated sequences of characters. Both inputs to
strcat must be NUL-terminated, and the result will be NUL-terminated. It
wouldn't be useful for strcat to write an extra NUL-byte to the result if it
doesn't need to.
(And if you're wondering what if the input strings have multiple trailing
NUL bytes already, I propose another thought experiment: how would strcat know
how many trailing NUL-bytes there are in a string?)
BTW, since you tagged this with "best-practices", I'll also recommend that you take care not to write past the end of your destination buffers. Typically this means avoiding strcat and strcpy (unless you've already checked that the input strings won't overflow the destination) and using safer versions (e.g. strncat. Note that strncpy has its own pitfalls, so that's a poor substitute. There also are safer versions that are non-standard, such as strlcpy/strlcat and strcpy_s/strcat_s.)
Similarly, functions like your foo function always should take an additional argument specifying what the size of the destination buffer is (and documentation should make it explicitly clear whether that size accounts for a NUL terminator or not).
How can I find out the last character
from a string?
Your technique with str[strlen(str) - 1] is fine. As pointed out, you should avoid repeated, unnecessary calls to strlen and store the results.
I somehow think that, this is not the
correct way because strlen has to
iterate over the characters to get the
length. So this operation will have a
O(n) complexity.
Repeated calls to strlen can be a bane of C programs. However, you should avoid premature optimization. If a profiler actually demonstrates a hotspot where strlen is expensive, then you can do something like this for your literal string case:
const char test[] = "foo";
sizeof test // 4
Of course if you create 'test' on the stack, it incurs a little overhead (incrementing/decrementing stack pointer), but no linear time operation involved.
Literal strings are generally not going to be so gigantic. For other cases like reading a large string from a file, you can store the length of the string in advance as but one example to avoid recomputing the length of the string. This can also be helpful as it'll tell you in advance how much memory to allocate for your character buffer.
I have a string and need to append a
char to it. How can i do that? strcat
accepts only char*.
If you have a char and cannot make a string out of it (char* c = "a"), then I believe you can use strncat (need verification on this):
char ch = 'a';
strncat(str, &ch, 1);
In the above code,delimiter is a local
variable which gets destroyed after
foo returned. Is it OK to append it to
variable output?
Yes: functions like strcat and strcpy make deep copies of the source string. They don't leave shallow pointers behind, so it's fine for the local data to be destroyed after these operations are performed.
If I am concatenating two null
terminated strings, will strcat
append two null terminating characters
to the resultant string?
No, strcat will basically overwrite the null terminator on the dest string and write past it, then append a new null terminator when it's finished.
How can I find out the last character from a string?
Your approach is almost correct. The only way to find the end of a C string is to iterate throught the characters, looking for the nul.
There is a bug in your answer though (in the general case). If strlen(str) is zero, you access the character before the start of the string.
I have a string and need to append a char to it. How can i do that?
Your approach is wrong. A C string is just an array of C characters with the last one being '\0'. So in theory, you can append a character like this:
char delimiter = ',';
char text[7];
strcpy(text, "hello");
int textSize = strlen(text);
text[textSize] = delimiter;
text[textSize + 1] = '\0';
However, if I leave it like that I'll get zillions of down votes because there are three places where I have a potential buffer overflow (if I didn't know that my initial string was "hello"). Before doing the copy, you need to put in a check that text is big enough to contain all the characters from the string plus one for the delimiter plus one for the terminating nul.
... delimiter is a local variable which gets destroyed after foo returned. Is it OK to append it to variable output?
Yes that's fine. strcat copies characters. But your code sample does no checks that output is big enough for all the stuff you are putting into it.
If I am concatenating two null terminated strings, will strcat append two null terminating characters to the resultant string?
No.
I somehow think that, this is not the correct way because strlen has to iterate over the characters to get the length. So this operation will have a O(n) complexity.
You are right read Joel Spolsky on why C-strings suck. There are few ways around it. The ways include either not using C strings (for example use Pascal strings and create your own library to handle them), or not use C (use say C++ which has a string class - which is slow for different reasons, but you could also write your own to handle Pascal strings more easily than in C for example)
Regarding adding a char to a C string; a C string is simply a char array with a nul terminator, so long as you preserve the terminator it is a string, there's no magic.
char* straddch( char* str, char ch )
{
char* end = &str[strlen(str)] ;
*end = ch ;
end++ ;
*end = 0 ;
return str ;
}
Just like strcat(), you have to know that the array that str is created in is long enough to accommodate the longer string, the compiler will not help you. It is both inelegant and unsafe.
If I am concatenating two null
terminated strings, will strcat append
two null terminating characters to the
resultant string?
No, just one, but what ever follows that may just happen to be nul, or whatever happened to be in memory. Consider the following equivalent:
char* my_strcat( char* s1, const char* s2 )
{
strcpy( &str[strlen(str)], s2 ) ;
}
the first character of s2 overwrites the terminator in s1.
In the above code,delimiter is a local
variable which gets destroyed after
foo returned. Is it OK to append it to
variable output?
In your example delimiter is not a string, and initialising a pointer with a char makes no sense. However if it were a string, the code would be fine, strcat() copies the data from the second string, so the lifetime of the second argument is irrelevant. Of course you could in your example use a char (not a char*) and the straddch() function suggested above.
I'm using a char[] of size 4 but when I use memcpy() function it stores 8 characters in it and also the character array length becomes 8. What is happing?
I don't want to use malloc ok.
char strRoh[4]={'\0'};
and then
memcpy(strRoh,Dump+22,4);
Now tell me whats wrong with this
char strIP[]="hhhhhhhh";
char strRoh[4]={'\0'};
char strTheta[4]={'\0'};
char strTimeStamp[6]={'\0'};
char strNMDump[48]={'\0'};
is there any problem with decelerations cause when i change there order they strings also change there size now strroh is getting 10 chars
what a hell is going on with this
C strings are 0-terminated. This means that if you want to have a string of length n in C, you need n+1 chars for it:
char hello[5] = "hello";
is not a string, because hello has space for 5 chars, and it doesn't end with 0.
char hello[6] = "hello";
is a string, and has 6 characters: h, e, l, l, o, 0.
To be able to use string related functions in C, you need the terminating 0.
So, change your code to have:
char strRoh[5]={'\0'};
char strTheta[5]={'\0'};
char strTimeStamp[7]={'\0'};
char strNMDump[49]={'\0'};
Note that in C, when you do:
char hello[] = "hello";
the compiler does the counting for you, and makes hello an array of size 6 (one terminating 0):
printf("%zu\n", sizeof hello);
will print 6.
The underlying type of the objects pointed by both the source and destination pointers are irrelevant for memcpy; The result is a binary copy of the data.
The function does not check for any terminating null character in source - it always copies exactly num bytes. My guess is you are not adding a terminating null and trying to access it as a string.
C does not have any kind of boundary check on its data types.
So what you are probably "seeing" when debugging the code is that it shows you 8 bytes in the array. As someone else says, you might be trying to view it as a string and do not have a terminating zero byte. This is quite normal in C, and it is one of the aspects of the language that makes it very hard to understand.
I can recommend you read a good introduction to memory and pointer handling under C, or switch to a managed language like C#, VB.NET, Java, Perl, Python etc.
I suppose that if char has 2 bytes if you memcpy to a byte array you might be getting 8 bytes, that is 2 bytes for each char.
I am however rusty at this C/C++ things. So hopefully somebody with more experience will give you a better answer.
The problem is you have a char array of 4 bytes and you writing full 4 bytes during memcpy without leaving any space for the terminating null character. Declare your array as 5 bytes and initialize it all to null (which you are already doing) and everything should be fine.