Character array seems to grow after memcpy(), what is the problem? - c

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.

Related

How does a String terminate in C?

I know the string in c will be terminated by a character \0.
However, if I do char a[5]="abcd\n" , where would \0 be?
Or do I need to reserve at least one position for \0, whenever I try to use char[] to store a string?
Thank you for any help!
You should do:
char a[]="abcd\n";
without specifying the size to let compiler figure out the buffer size. The actual buffer will have size of 6 to accommodate your 5 bytes + 1 byte for terminating zero. When you type "something" without assignment, compilaer puts that string in a dedicated place in the program with at least 1 zero byte after the last character.
Writing
char a[5]="abcd\n"
is a bad practice because it will cause functions like strcpy() to act in undefined manner as your variable 'a' is not a c string, but just a buffer of characters, which by chance seem to be all printable/visible + terminating \n

What happens when I write `char str[80];`?

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.

Get length of item in multiple dimension array C

I construct an array with:
char *state[] = {"California", "Oregon", "Texas"};
I want to get the length of California which should be 10 but when I do sizeof(state[0]), it just gives me 8 ( I think this means 8 bytes since the size of a char is 1 byte). But why 8 though instead of 10? I'm still able to print out each chars of California by looping through state[0][i].
I'm new to C, can someone please explain this to me?
The simplest explanation is that sizeof is a compile-time evaluated expression. Therefore it knows nothing about the length of a string which is essentially something that needs to be evaluated at run-time.
To get the length of a string, use strlen. That returns the length of a string not including the implicit null-terminator that tells the C runtime where the end of the string is.
One other thing, it's a good habit to get into using const char* [] when setting up a string array. This reinforces the fact that it's undefined behaviour to modify any of the array contents.

char arrays in c end char

I'm reading from a socket into a char array and I want to know when to stop reading. The terminating char sequence is '\r\n\r\n'. If what I read in is smaller than the array size I don't want to loop around anymore. My question is really if I load into the array say 10 characters and it has length 20, what is the array[20] index set to?
Thanks
edit:
Sorry I did mean array[19], setting the last index to NULL as suggested? seems like an appropriate solution. To give some more detail, I need to know when all the data has been read from the socket. I don't know the size of the data to be sent only that it terminates with '\r\n\r\n'
If it has length 20, then array[20] is outside your array and shouldn't be accessed like that (unless you want to do some sort of wizardy and hacking beyond your explanation).
EDIT: If you meant array[19], then no. You need to set the NUL character at array index = size of string received. ASCII NUL character '\0' is not C NULL constant, which for 32-bits machines would be 4-byte long, and that would potentially overwrite data.
My question is really if I load into the array say 10 characters and it has length 20, what is the array[20] index set to?
It's not set to anything. Feel free to set it to something yourself (for instance, a null terminator).
Generally in the name of efficiency C does not initialize an array to any known value, so you'll get whatever was leftover in memory.
You can explicitly initialize the array to fix this. A common initialization for a sequence of bytes is zero, which won't match your search string and will act as and end-of-string if you try to process the array as a string.
char array[20] = {0}; /* the extra elements are always initialized to 0 as well */
char array2[20];
memset(array2, 0, sizeof(array2));
I'll presume you had a typo and meant array[19] instead of array[20].
In C, when the array is malloced, the array has whatever is leftover in the malloced chunk of memory. If you copy several chars into the array and want the chars to be read as a string, you have to set the next char after the last char to be '\0'.
Since you know when to stop reading, you could set the next char in your array to '\0' to mark the end of the string.
To the best of my knowledge, the ANSI C standard does not describe what value should be allocated to uninitialized arrays. Consider it to be garbage and assume that nothing can be said about it. Although, I have mostly observed them to be 0 (using gcc). This implementation may vary across compilers.
Also, this value could depend on the previous steps which have modified array[19] (as mOskitO pointed out, array[20] is out of bounds).

second memcpy() attaches previous memcpy() array to it

I have a little problem here with memcpy()
When I write this
char ipA[15], ipB[15];
size_t b = 15;
memcpy(ipA,line+15,b);
It copies b bytes from array line starting at 15th element (fine, this is what i want)
memcpy(ipB,line+31,b);
This copies b bytes from line starting at 31st element, but it also attaches to it the result for previous command i.e ipA.
Why? ipB size is 15, so it shouldnt have enough space to copy anything else. whats happening here?
result for ipA is 192.168.123.123
result for ipB becomes 205.123.123.122 192.168.123.123
Where am I wrong? I dont actually know alot about memory allocation in C.
It looks like you're not null-terminating the string in ipA. The compiler has put the two variables next to one another in memory, so string operations assume that the first null terminator is sometime after the second array (whenever the next 0 occurs in memory).
Try:
char ipA[16], ipB[16];
size_t b = 15;
memcpy(ipA,line+15,b);
ipA[15] = '\0';
memcpy(ipB,line+31,b);
ipB[15] = '\0';
printf("ipA: %s\nipB: %s\n", ipA, ipB)
This should confirm whether this is the problem. Obviously you could make the code a bit more elegant than my test code above. As an alternative to manually terminating, you could use printf("%.*s\n", b, ipA); or similar to force printf to print the correct number of characters.
Are you checking the content of the arrays by doing printf("%s", ipA) ? If so, you'll end up with the described effect since your array is interpreted as a C string which is not null terminated. Do this instead: printf("%.*s", sizeof(ipA), ipA)
Character strings in C require a terminating mark. It is the char value 0.
As your two character strings are contiguous in memory, if you don't terminate the first character string, then when reading it, you will continue until memory contains the end-of-string character.

Resources