My application falls over when I make the following call to strcat any ideas why?
char *encryptedLine[255] = {0};
char encryptedLString[8];
sprintf(encryptedLString, "%08lX", L);
strcat(*encryptedLine, encryptedLString);
*encryptedLine is NULL pointer: it needs to point a char buffer.
*encyptedLine is equivalent to encryptedLine[0], which is the first entry in the array of char* encryptedLine:
char *encryptedLine[255] = { 0 };
which is a NULL pointer.
To fix, either change to:
char encryptedLine[255] = { 0 };
strcat(encryptedLine, encryptedString);
or:
encryptedLine[0] = malloc(255);
strcat(*encryptedLine, encryptedString);
I think you also need to increase the size of encryptedLString by 1 as:
sprintf(encryptedLString, "%08lX", L);
will attempt to write 9 characters: 8 specified by the format plus 1 for the null terminator:
char encryptedLString[9];
encryptedLine is an array of 255 pointers initialized to NULL. *encryptedLine is a NULL pointer. You are passing a NULL pointer as the first argument to strcat, so it fails.
You are trying to strcat() with 0 as first parameter. *encryptedLine is encryptedLine[0] and you assigned {0} to it
You have an array of char pointers
char *encryptedLine[255]
You haven't allocated any memory and assigned it to any of them. Crash.
/* LINE 1*/ char *encryptedLine[255] = {0};
char encryptedLString[8];
sprintf(encryptedLString, "%08lX", L);
strcat(*encryptedLine, encryptedLString);
Look at LINE1, it allocates an array of 255 pointers to char that are all initialised to 0, then you do a strcat, which will try to write the value from encryptedLString into the location pointed to by the pointer *encryptedLine which is NULL, which isn't allowed.
Just allocate some memory for encryptedLine's pointers, and this program won't crash.
Related
I have this program:
#include<stdio.h>
void copy_string(char string1[], char string2[]){
int counter=0;
while(string1[counter]!='\0'){
string2[counter] = string1[counter];
counter++;
}
string2[counter] = '\0';
}
int main() {
char* myString = "Hello there!";
char* myStringCopy;
copy_string(myString, myStringCopy);
printf("%s", myStringCopy);
}
My question is, why isn't it working unless I declare myStringCopy as a fixed-size variable (char myStringCopy[12];)? Shouldn't it work if I add a \0 character after the copy as I'm doing?
It can work by doing char* myStringCopy as long as you allocate memory space for it.
for example
char* myStringCopy
myStringCopy = malloc(sizeof(char) * (strlen(myString)+1))
I might be mistaken about the +1 but I think it is like this.
char myStringCopy[12]; tells the compiler to create an array of 12 char. When myStringCopy is passed to copy_string, this array is automatically converted to a pointer to its first element, so copy_string receives a pointer to the characters.
char *myStringCopy; tells the compiler to create a pointer to char. The compiler creates this pointer, including providing memory for it, but it does not set the value of the pointer. When this pointer is passed to copy_string, copy_string does not receive a valid value.
To make char *myStringCopy; work, you must allocate memory (which you can do with malloc). For example, you could use:
char *myStringCopy;
myStringCopy = malloc(13 * sizeof *myStringCopy);
if (myStringCopy == NULL)
{
fprintf(stderr, "Error, the malloc did not work.\n");
exit(EXIT_FAILURE);
}
Also, note that 12 is not enough. The string “Hello there!” contains 12 characters, but it also includes a terminating null character. You must provide space for the null character. char myStringCopy[12]; appeared to work, but copy_string was actually writing a thirteenth character beyond the array, damaging something else in your program.
The problem is that you don't have room for mystringCopy
You need to reserve space first:
char* myString = "Hello there!";
char* myStringCopy = malloc(strlen(myString) + 1);
char* myStringCopy;
This is only pointer to char*. You must first allocate memory for myStringCopy, before start copy. When you declare it like this:
char myStringCopy[12];
compiler allocate enough memory in stack.
I am working on a short program that reads a .txt file. Intially, I was playing around in main function, and I had gotten to my code to work just fine. Later, I decided to abstract it to a function. Now, I cannot seem to get my code to work, and I have been hung up on this problem for quite some time.
I think my biggest issue is that I don't really understand what is going on at a memory/hardware level. I understand that a pointer simply holds a memory address, and a pointer to a pointer simply holds a memory address to an another memory address, a short breadcrumb trail to what we really want.
Yet, now that I am introducing malloc() to expand the amount of memory allocated, I seem to lose sight of whats going on. In fact, I am not really sure how to think of memory at all anymore.
So, a char takes up a single byte, correct?
If I understand correctly, then by a char* takes up a single byte of memory?
If we were to have a:
char* str = "hello"
Would it be say safe to assume that it takes up 6 bytes of memory (including the null character)?
And, if we wanted to allocate memory for some "size" unknown at compile time, then we would need to dynamically allocate memory.
int size = determine_size();
char* str = NULL;
str = (char*)malloc(size * sizeof(char));
Is this syntactically correct so far?
Now, if you would judge my interpretation. We are telling the compiler that we need "size" number of contiguous memory reserved for chars. If size was equal to 10, then str* would point to the first address of 10 memory addresses, correct?
Now, if we could go one step further.
int size = determine_size();
char* str = NULL;
file_read("filename.txt", size, &str);
This is where my feet start to leave the ground. My interpretation is that file_read() looks something like this:
int file_read(char* filename, int size, char** buffer) {
// Set up FILE stream
// Allocate memory to buffer
buffer = malloc(size * sizeof(char));
// Add characters to buffer
int i = 0;
char c;
while((c=fgetc(file))!=EOF){
*(buffer + i) = (char)c;
i++;
}
Adding the characters to the buffer and allocating the memory is what is I cannot seem to wrap my head around.
If **buffer is pointing to *str which is equal to null, then how do I allocate memory to *str and add characters to it?
I understand that this is lengthy, but I appreciate the time you all are taking to read this! Let me know if I can clarify anything.
EDIT:
Whoa, my code is working now, thanks so much!
Although, I don't know why this works:
*((*buffer) + i) = (char)c;
So, a char takes up a single byte, correct?
Yes.
If I understand correctly, by default a char* takes up a single byte of memory.
Your wording is somewhat ambiguous. A char takes up a single byte of memory. A char * can point to one char, i.e. one byte of memory, or a char array, i.e. multiple bytes of memory.
The pointer itself takes up more than a single byte. The exact value is implementation-defined, usually 4 bytes (32bit) or 8 bytes (64bit). You can check the exact value with printf( "%zd\n", sizeof char * ).
If we were to have a char* str = "hello", would it be say safe to assume that it takes up 6 bytes of memory (including the null character)?
Yes.
And, if we wanted to allocate memory for some "size" unknown at compile time, then we would need to dynamically allocate memory.
int size = determine_size();
char* str = NULL;
str = (char*)malloc(size * sizeof(char));
Is this syntactically correct so far?
Do not cast the result of malloc. And sizeof char is by definition always 1.
If size was equal to 10, then str* would point to the first address of 10 memory addresses, correct?
Yes. Well, almost. str* makes no sense, and it's 10 chars, not 10 memory addresses. But str would point to the first of the 10 chars, yes.
Now, if we could go one step further.
int size = determine_size();
char* str = NULL;
file_read("filename.txt", size, &str);
This is where my feet start to leave the ground. My interpretation is that file_read() looks something like this:
int file_read(char* filename, int size, char** buffer) {
// Set up FILE stream
// Allocate memory to buffer
buffer = malloc(size * sizeof(char));
No. You would write *buffer = malloc( size );. The idea is that the memory you are allocating inside the function can be addressed by the caller of the function. So the pointer provided by the caller -- str, which is NULL at the point of the call -- needs to be changed. That is why the caller passes the address of str, so you can write the pointer returned by malloc() to that address. After your function returns, the caller's str will no longer be NULL, but contain the address returned by malloc().
buffer is the address of str, passed to the function by value. Allocating to buffer would only change that (local) pointer value.
Allocating to *buffer, on the other hand, is the same as allocating to str. The caller will "see" the change to str after your file_read() returns.
Although, I don't know why this works: *((*buffer) + i) = (char)c;
buffer is the address of str.
*buffer is, basically, the same as str -- a pointer to char (array).
(*buffer) + i) is pointer arithmetic -- the pointer *buffer plus i means a pointer to the ith element of the array.
*((*buffer) + i) is dereferencing that pointer to the ith element -- a single char.
to which you are then assigning (char)c.
A simpler expression doing the same thing would be:
(*buffer)[i] = (char)c;
with char **buffer, buffer stands for the pointer to the pointer to the char, *buffer accesses the pointer to a char, and **buffer accesses the char value itself.
To pass back a pointer to a new array of chars, write *buffer = malloc(size).
To write values into the char array, write *((*buffer) + i) = c, or (probably simpler) (*buffer)[i] = c
See the following snippet demonstrating what's going on:
void generate0to9(char** buffer) {
*buffer = malloc(11); // *buffer dereferences the pointer to the pointer buffer one time, i.e. it writes a (new) pointer value into the address passed in by `buffer`
for (int i=0;i<=9;i++) {
//*((*buffer)+i) = '0' + i;
(*buffer)[i] = '0' + i;
}
(*buffer)[10]='\0';
}
int main(void) {
char *b = NULL;
generate0to9(&b); // pass a pointer to the pointer b, such that the pointer`s value can be changed in the function
printf("b: %s\n", b);
free(b);
return 0;
}
Output:
0123456789
if you point a char pointer to a chunk of memory that you just malloc() and feed it characters at position [0], [1], [2], [3],..., [n] does malloc already provide a null terminator '\0' at the end or must i provide it at the last element of the char array?
int i;
char B; //has the characters hello
char *A=malloc(5*sizeof(char)); //4 bytes for hello + 1 byte for null terminator?
for(i=0; i<strlen(A);i++)
A[i]=B[i];
after the for loop finishes should i add a null terminator to the last element of A or does malloc() already provide it?
YES you need to put a null terminator explicitly. malloc is just returning starting pointer to the block of 5 byte memory.
After malloc, A contains garbage value, so you need to assign \0 explicitly. However, there are several other errors in your code:
Your declaration of B is wrong, it should be a char array instead of a single char.
The string "hello" contains 6 elements, including the trailing \0, so:
char B[] = "hello";
char *A = malloc(strlen(B) + 1);
for(i = 0; i < strlen(B) + 1; i++)
A[i] = B[i];
Or you can simply use strcpy:
strcpy(A, B);
Malloc will not provide memory filled with nulls.
As pointed out above, use strcpy and be safe.
I edited out the calloc part. That was wrong.
Here is my code:
printf("%s\n", "test1");
char c = '2';
char * lines[2];
char * tmp1 = lines[0];
*tmp1 = c;
printf("%s\n", "test2");
I don't see the second printf in console.
Question: Can anybody explain me what's wrong with my code?
NOTE: I'm trying to learn C :)
This line:
char * lines[2];
declares an array of two char pointers. However, you don't actually initialize the pointers to anything. So later when you do *tmp1 = (char)c; then you assign the character c to somewhere in memory, possibly even address zero (i.e. NULL) which is a bad thing.
The solution is to either create the array as an array of arrays, like
char lines[2][30];
This declares lines to have two arrays of 30 characters each, and since strings needs a special terminator character you can have string of up to 29 characters in them.
The second solution is to dynamically allocate memory for the strings:
char *lines[2];
lines[0] = malloc(30);
lines[1] = malloc(30);
Essentially this does the same as the above array-of-arrays declaration, but allocates the memory on the heap.
Of course, maybe you just wanted a single string of a single character (plus the terminator), then you were almost right, just remove the asterisk:
char line[2]; /* Array of two characters, or a string of length one */
The array lines in uninitialized. Thus lines[0] is an uninitalized pointer. Dereferencing it in *tmp1 is sheer undefined behaviour.
Here's an alternative, that may or may not correspond to what you want:
char lines[2];
char * tmp1 = lines; // or "&lines[0]"
*tmp = c;
Or, more easily:
char lines[2] = { c, 0 };
lines is uninitialized, and tmp1 initialization is wrong.
It should be:
char lines[2];
char * tmp1 = lines;
Alternatively, you can say:
char * tmp1 = &lines[0];
Or else for an array of strings:
char lines[2][30];
char * tmp1 = lines[0];
The line
char * lines[2];
creates an array of two char pointers. But that doesn't allocate memory, it's just a "handle" or "name" for the pointer in memory. The pointer doesn't point to something useful.
You will either have to allocate memory using malloc():
char * lines = malloc(2);
or tell the compiler to allocate memory for you:
char lines[2];
Note: Don't forget to terminate the string with a 0 byte before you use it.
char *lines[2]; : A two element array of char pointers.
char *tmp; : A pointer to a character.
char *tmp = lines[0] : The value inside the array element 0 of the lines array is transferred into tmp. Because it is an automatic array, therefore it will have garbage as the value for lines[0].
*temp : Dereference the garbage value. Undefined Behaviour.
char * tmp1 = lines[0];
here you declare a char pointer and initialize its pointer value to line[0],the fist element stored in line array which is also uninitialized.
now the tmp is pointing to somewhere unknown and not actually accessible. When you
*tmp1 = (char)c;
you are operating on a invalid memory address which causes a Segmentation fault.
I have defined a char array:
char d[6];
Correct me if I'm wrong regarding following:
At this moment no memory is allocated for variable d. Now I'm going to initialize it:
d="aaaaa";
After this kind of initialization, there would be no need to free memory; it will be done automatically.
How do I know if the char[] was initialized? I am looking for a pattern like
if (filled(d)){..}
Also, how do I fill char[] with one kind of character?
At this moment no memory allocated for variable d.
Incorrect. This:
char d[6];
is an uninitialised array of 6 chars and memory, on stack, has been allocated for it. Stack variables do not need to be explicitly free()d, whether they are initialised or not. The memory used by a stack variable will be released when it goes out of scope. Only pointers obtained via malloc(), realloc() or calloc() should be passed to free().
To initialise:
char d[6] = "aaaaa"; /* 5 'a's and one null terminator. */
or:
char d[] = "aaaaa"; /* The size of the array is inferred. */
And, as already noted by mathematician1975, array assignment is illegal:
char d[] = "aaaaa"; /* OK, initialisation. */
d = "aaaaa"; /* !OK, assignment. */
strcpy(), strncpy(), memcpy(), snprintf(), etc can be used to copy into d after declaration, or assignment of char to individual elements of d.
How to know was char[] initialized? I need pattern if filled(d){..}
If the arrays are null terminated you can use strcmp()
if (0 == strcmp("aaaaaa", d))
{
/* Filled with 'a's. */
}
or use memcmp() if not null terminated:
if (0 == memcmp("aaaaaa", d, 6))
{
/* Filled with 'a's. */
}
How to fill char[] with one kind of characters?
Use memset():
memset(d, 'a', sizeof(d)); /* WARNING: no null terminator. */
or:
char d[] = { 'a', 'a', 'a', 'a', 'a', 'a' }; /* Again, no null. */
Your code will not compile (gcc 4.6.3) if you do
char d[6];
d = "aaaaa";
you will need to do
char d[6] = "aaaaa"
to initialise it this way.
This is a local variable created on the stack and so in terms of memory issues all you need worry about is not writing/reading beyond the array bounds.
First, whenever you declare char d[6] 6 bytes of memory is already allocated.
Second, no need to free your memory unless you do malloc
Third, if you want to initialize it with one kind of character then do this
char d[6] = "aaaaa";
int d[6];
6 bytes will be allocated onto the stack with this declaration. It will be freed automatically.
How to know was char[] initialized? I need pattern if filled(d){..}
Just do this while declaring the character array:
char d[6];
d[0] = 0;
Then you can check like this:
if(strlen(d) == 0)
//d is not initialized