Array fill in C - c

I have this problem with a lot of arrays in my program, and I can't understand why. I think I miss something on array theory.
"Someone" adds at the end of my arrays some sort of char characters such as ?^)(&%. For example if I have an array of lenght 5 with "hello", so it's full, sometimes it prints hello?()/&%%. I can undesrtand it can occur if it's of 10 elements and i use only 5, so maybe the other 5 elements get some random values, but if it's full, where the hell gets those strange values?
I partially solve it by manaully adding at the end the character '\0'.
For example this problem occurs, sometimes, when I try to fill an array from another array (i read a line form a test file with fgets, then I have to extract single words):
...
for(x=0;fgets(c,500,fileb);x++) { // read old local file
int l=strlen(c);
i=0;
for (k=0;k<(l-34);k++) {
if(c[k+33]!='\n') {
userDatabaseLocalPath[k]=c[k+33];
}
}
Thanks

Strings in C are terminated by a character with the value 0, often referred to as a character literal, i.e. '\0'.
A character array of size 5 can not hold the string hello, since the terminator doesn't fit. Functions expecting a terminator will be confused.
To declare an array holding a string, the best syntax to use is:
char greeting[] = "hello";
This way, you don't need to specify the length (count the characters), since the compiler does that for you. And you also don't need to include the terminator, it's added automatically so the above will create this, in memory:
+-+-+-+-+-+--+
greeting: |h|e|l|l|o|\0|
+-+-+-+-+-+--+
You say that you have problems "filling an array from another longer array", this sounds like an operation most referred to as string copying. Since strings are just arrays with terminators, you can't blindly copy a longer string over a shorter, unless you know that there is extra space.
Given the above, this code would invoke undefined behavior:
strcpy(greeting, "hi there!");
since the string being copied into the greeting array is longer than what the array has space for.
This is typically avoided by using "known to be large enough" buffers, or adding checks that manually keep track of the space used. There is a function called strncpy() which sort of does this, but I would not recommend using it since its exact semantics are fairly odd.

You are facing the issue of boundary limit for the array.. if the array is of size 5 , then its not necessary that the sixth location which will be \0 be safe.. As it is not memory reserved/assigned for your array.. If after sometime some other application accesses this memory and writes to it. you will lose the \0 resulting in the string helloI accessed this space being read. which is what you are getting.

Related

Properties of strcpy()

I have a global definition as following:
#define globalstring "example1"
typedef struct
{
char key[100];
char trail[10][100];
bson_value_t value;
} ObjectInfo;
typedef struct
{
ObjectInfo CurrentOrderInfoSet[5];
} DataPackage;
DataPackage GlobalDataPackage[10];
And I would like to use the strcpy() function in some of my functions as following:
strcpy(GlobalDataPackage[2].CurrentOrderInfoSet[0].key, "example2");
char string[100] = "example3";
strcpy(GlobalDataPackage[2].CurrentOrderInfoSet[0].key, string);
strcpy(GlobalDataPackage[2].CurrentOrderInfoSet[0].key, globalstring);
First question: Are the global defined strings all initiated with 100 times '\0'?
Second qestion: I am a bit confused as to how exactly strcpy() works. Does it only overwrite the characters necessary to place the source string into the destination string plus a \0 at the end and leave the rest as it is or does it fully delete any content of the destination string prior to that?
Third question: All my strings are fixed length of 100. If I use the 3 examples of strcpy() above, with my strings not exceeding 99 characters, does strcpy() properly overwrite the destination string and NULL terminate it? Meaning do I run into problems when using functions like strlen(), printf() later?
Fourth question: What happens when I strcpy() empty strings?
I plan to overwrite these strings in loops various times and would like to know if it would be safer to use memset() to fully "empty" the strings prior to strcpy() on every iteration.
Thx.
Are the global defined strings all initiated with 100 times '\0'?
Yes. Global char arrays will be initilizated to all zeros.
I am a bit confused as to how exactly strcpy() works. Does it only overwrite the characters necessary to place the source string into the destination string plus a \0 at the end and leave the rest as it
Exactly. It copies the characters up until and including '\0' and does not care about the rest.
If I use ... my strings not exceeding 99 characters, does strcpy() properly overwrite the destination string and NULL terminate it?
Yes, but NULL is a pointer, it's terminated with zero byte, sometimes called NUL. You might want to see What is the difference between NUL and NULL? .
Meaning do I run into problems when using functions like strlen(), printf() later?
Not if your string lengths are less than or equal to 99.
What happens when I strcpy() empty strings?
It just copies one zero byte.
would like to know if it would be safer to use memset() to fully "empty" the strings prior to strcpy() on every iteration.
Safety is a broad concept. As far as safety as in if the program will execute properly, there is no point in caring about anything after zero byte, so just strcpy it.
But you should check if your strings are less than 99 characters and handle what to do it they are longer. You might be interested in strnlen, but the interface is confusing - I recommend to use memcpy + explicitly manually set zero byte.

Does specifying array size for a user input string in C matter?

I am writing a code to take a user's input from the terminal as a string. I've read online that the correct way to instantiate a string in C is to use an array of characters. My question is if I instantiate an array of size [10], is that 10 indexes? 10 bits? 10 bytes? See the code below:
#include <stdio.h>
int main(int argc, char **argv){
char str[10] = "Jessica";
scanf("%s", &str);
printf("%c\n", str[15]);
}
In this example "str" is initialized to size 10 and I am able to to print out str[15] assuming that when the user inputs a a string it goes up to that index.
My questions are:
Does the size of the "str" array increase after taking a value from scanf?
At what amount of string characters will my original array have overflow?
.
When you declare an array of char as you have done:
char str[10] = "Jessica";
then you are telling the compiler that the array will hold up to 10 values of the type char (generally - maybe even always - this is an 8-bit character). When you then try to access a 'member' of that array with an index that goes beyond the allocated size, you will get what is known as Undefined Behaviour, which means that absolutely anything may happen: your program may crash; you may get what looks like a 'sensible' value; you may find that your hard disk is entirely erased! The behaviour is undefined. So, make sure you stick within the limits you set in the declaration: for str[n] in your case, the behaviour is undefined if n < 0 or n > 9 (array indexes start at ZERO). Your code:
printf("%c\n", str[15]);
does just what I have described - it goes beyond the 'bounds' of your str array and, thus, will cause the described undefined behaviour (UB).
Also, your scanf("%s", &str); may also cause such UB, if the user enters a string of characters longer than 9 (one must be reserved for a terminating nul character)! You can prevent this by telling the scanf function to accept a maximum number of characters:
scanf("%9s", str);
where the integer given after the % is the maximum input length allowed (anything after this will be ignored). Also, as str is defined as an array, then you don't need the explicit "address of" operator (&) in scanf - it is already there, as an array reference decays to a pointer!
Hope this helps! Feel free to ask for further clarification and/or explanation.
One of C's funny little foibles is that in almost all cases it does not check to make sure you are not overflowing your arrays.
It's your job to make sure you don't access outside the bounds of your arrays, and if you accidentally do, almost anything can happen. (Formally, it's undefined behavior.)
About the only thing that can't happen is that you get a nice error message
Error: array out-of-bounds access at line 23
(Well, theoretically that could happen, but in practice, virtually no C implementation checks for array bounds violations or issues messages like that.)
See also this answer to a similar question.
An array declares the given number of whatever you are declaring. So in the case of:
char str[10]
You are declaring an array of ten chars.
Does the size of the "str" array increase after taking a value from scanf?
No, the size does not change.
At what amount of string characters will my original array have overflow?
An array of 10 chars will hold nine characters and the null terminator. So, technically, it limits the string to nine characters.
printf("%c\n", str[15]);
This code references the 16th character in your array. Because your array only holds ten characters, you are accessing memory outside of the array. It's anyone's guess as to if your program even owns that memory and, if it does, you are referencing memory that is part of another variable. This is a recipe for disaster.

C language, char=char with unexpected results

Hi everybody and thanks in advance for any help, this is the situation:
#define N 12
[..]
char vect[N][2];
char strng[2];
[..]
vect[i][0]=strng[2]; //this two lines are in a simple for cycle
vect[i][2]=strng[0];
Now, if in string[2] I have "c 2", what I expect in vect[i][0] is '2' and in vect[i][1] 'c'.
I use code::blocks and watching vect I have instead "2#", but it could be "2À" as well.
Can you help me? Where am I wrong?
Array indexes goes from zero up to the size minus one. So using e.g. strng[2] you access the third entry in the two-entry array. Accessing an array out of bounds leads to undefined behavior and the data will be indeterminate.
You should also remember that all strings in C are one more character than reported by e.g. strlen, and that extra character is a special terminator character. So if you want a two-character string, you really need three characters: Two for the string, and one for the terminator.
Rewrite these statements
vect[i][0]=strng[2]; //this two lines are in a simple for cycle
vect[i][2]=strng[0];
the following way
vect[i][0]=strng[1]; //this two lines are in a simple for cycle
vect[i][1]=strng[0];
provided that string contains two characters { 'c', '2' }.
Take into account that array string can not have string literal "c 2", because you defined it as
char strng[2];
that is it can contain only two characters.
If you want that the array would contain indeed "c 2" then you have to define it either as
char strng[3];
or as
char strng[4];
if you want to include the terminating zero.
In this case you may write
vect[i][0]=strng[2]; //this two lines are in a simple for cycle
vect[i][1]=strng[0];
Assuming strng literally contains "c 2", then your memory is the issue. strng[2] contains 3 cells iirc. 2 for holding chars and then a null terminator (ie \0). so when you try to access strng[2], (which you cant because you can only go to N-1 cells, where N is the number allocated for it) it contains undefined results, since it isnt null terminated and you are reaching beyond memory you allocated

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).

Strings without a '\0' char?

If by mistake,I define a char array with no \0 as its last character, what happens then?
I'm asking this because I noticed that if I try to iterate through the array with while(cnt!='\0'), where cnt is an int variable used as an index to the array, and simultaneously print the cnt values to monitor what's happening the iteration stops at the last character +2.The extra characters are of course random but I can't get it why it has to stop after 2.Does the compiler automatically inserts a \0 character? Links to relevant documentation would be appreciated.
To make it clear I give an example. Let's say that the array str contains the word doh(with no '\0'). Printing the cnt variable at every loop would give me this:
doh+
or doh^
and so on.
EDIT (undefined behaviour)
Accessing array elements outside of the array boundaries is undefined behaviour.
Calling string functions with anything other than a C string is undefined behaviour.
Don't do it!
A C string is a sequence of bytes terminated by and including a '\0' (NUL terminator). All the bytes must belong to the same object.
Anyway, what you see is a coincidence!
But it might happen like this
,------------------ garbage
| ,---------------- str[cnt] (when cnt == 4, no bounds-checking)
memory ----> [...|d|o|h|*|0|0|0|4|...]
| | \_____/ -------- cnt (big-endian, properly 4-byte aligned)
\___/ ------------------ str
If you define a char array without the terminating \0 (called a "null terminator"), then your string, well, won't have that terminator. You would do that like so:
char strings[] = {'h', 'e', 'l', 'l', 'o'};
The compiler never automatically inserts a null terminator in this case. The fact that your code stops after "+2" is a coincidence; it could just as easily stopped at +50 or anywhere else, depending on whether there happened to be \0 character in the memory following your string.
If you define a string as:
char strings[] = "hello";
Then that will indeed be null-terminated. When you use quotation marks like that in C, then even though you can't physically see it in the text editor, there is a null terminator at the end of the string.
There are some C string-related functions that will automatically append a null-terminator. This isn't something the compiler does, but part of the function's specification itself. For example, strncat(), which concatenates one string to another, will add the null terminator at the end.
However, if one of the strings you use doesn't already have that terminator, then that function will not know where the string ends and you'll end up with garbage values (or a segmentation fault.)
In C language the term string refers to a zero-terminated array of characters. So, pedantically speaking there's no such thing as "strings without a '\0' char". If it is not zero-terminated, it is not a string.
Now, there's nothing wrong with having a mere array of characters without any zeros in it, as long as you understand that it is not a string. If you ever attempt to work with such character array as if it is a string, the behavior of your program is undefined. Anything can happen. It might appear to "work" for some magical reasons. Or it might crash all the time. It doesn't really matter what such a program will actually do, since if the behavior is undefined, the program is useless.
This would happen if, by coincidence, the byte at *(str + 5) is 0 (as a number, not ASCII)
As far as most string-handling functions are concerned, strings always stop at a '\0' character. If you miss this null-terminator somewhere, one of three things will usually happen:
Your program will continue reading past the end of the string until it finds a '\0' that just happened to be there. There are several ways for such a character to be there, but none of them is usually predictable beforehand: it could be part of another variable, part of the executable code or even part of a larger string that was previously stored in the same buffer. Of course by the time that happens, the program may have processed a significant amount of garbage. If you see lots of garbage produced by a printf(), an unterminated string is a common cause.
Your program will continue reading past the end of the string until it tries to read an address outside its address space, causing a memory error (e.g. the dreaded "Segmentation fault" in Linux systems).
Your program will run out of space when copying over the string and will, again, cause a memory error.
And, no, the C compiler will not normally do anything but what you specify in your program - for example it won't terminate a string on its own. This is what makes C so powerful and also so hard to code for.
I bet that an int is defined just after your string and that this int takes only small values such that at least one byte is 0.

Resources