I'm really new to C and all I know is that the error is related to oldname and newname not be initialized
#include <stdio.h>
int main (int argc, char const *argv[])
{
int result;
int lengthOne;
int lengthTwo;
lengthOne = sizeof(argv[0]);
lengthTwo= sizeof(argv[1]);
char oldname[lengthOne] = argv[0];
char newname[lengthOne] = argv[1];
result = rename(oldname, newname);
if (result == 0) {
puts "File renamed";
} else {
perror "ERROR: Could not rename file";
}
return 0;
}
app.c: In function ‘main’:
app.c:11: error: variable-sized object may not be initialized
app.c:12: error: variable-sized object may not be initialized
app.c:17: error: expected ‘;’ before string constant
app.c:19: error: expected ‘;’ before string constant
lengthOne = sizeof(argv[0]);
lengthTwo= sizeof(argv[1]);
This gives you the size of a char*, not the length of the string. You meant strlen, not sizeof.
char oldname[lengthOne] = argv[0];
char newname[lengthOne] = argv[1];
You can't assign to arrays like that. You could strcpy them, but it's unnecessary here because you can just use pointers.
const char* oldname = argv[0];
const char* newname = argv[1]; // But verify that argc >= 2 first!
EDIT: Also, don't forget that argv[0] is the name of the program itself, and argv[1] is the first argument. If your intent was to write a mv-like program instead of a program that renames itself, you want argv[1] and argv[2].
You seem to not be understanding what pointers are in C. This is a very core concept that you need to understand to be able to use the language.
I would start with a tutorial on them. A guick google brings this up as the first result: http://pw1.netcom.com/~tjensen/ptr/pointers.htm
First, char x[length] = /* something */; only works for string literals (i.e. "string" or {'s', 't', 'r', 'i', 'n', 'g', '\0'} if you want to be masochistic).
Second, to call a function, use parenthesis. puts("Text"); and printf("Text\n");. They are not optional like they are in some languages.
Third, as a function parameter (even if it's a parameter to main()), an array type decays to a pointer. So your function signature is effectively int main(int argc, char **argv) (and I prefer to write it that way, personally, but it makes no difference). You can't take the sizeof an array that has decayed to a pointer because it's not an array anymore and has no associated information about it's size. To get the size, use strlen().
Fourth, use a size_t to store sizes. Using an int to store sizes is wrong - there's no guarantee that int is large enough to hold sizes, and you can't have a -5 sized object of any kind. size_t is an unsigned integral type included in the standard for precisely this purpose.
Lastly, if you need a object whose size depends on runtime conditions, you can't use an array. You have to use a pointer, and use malloc to create a block of memory of the correct size, and then use free to destroy it when you're done. EDIT: Or just assign argv[0] to the pointer. argv is guaranteed in the standard to be writable, so you can edit it (just try to avoid appending anything).
sizeof is a compile-time check... the sizeof any argv element will be the number of bytes in a pointer-to-char. It has nothing to do with the run-time length of the text that pointer may address: strlen() returns that. But, C doesn't let you create dynamically (i.e. runtime) sized arrays. And even then you can't copy a string into another string with =... it requires a call to strcpy(dest, src). To make it work, obviously the easiest thing is:
result = rename(argv[0], argv[1])
But, I appreciate you're trying to learn how to copy the values into your own buffer. To do so, you need to dynamically create a sufficiently large buffer (memory-allocate or malloc), string-copy it, use it then free it. Several of these requirements are satisfied by the strdup() function:
const char* p_old_name = strdup(argv[0]);
const char* p_new_name = strdup(argv[1]);
rename(p_old_name, p_new_name);
free(p_old_name);
free(p_new_name);
Alternatively, you can statically specify a maximum size for the two strings (dangerous if you get it wrong - strncpy() can provide a more safety but a mistake may still prevent your program working with some long-but-valid paths):
#include <linux/limit.h> // or wherever you can find PATH_MAX or similar
...
char old_name[PATH_MAX];
char new_name[PATH_MAX];
strcpy(old_name, argv[0]);
strcpy(new_name, argv[1]);
rename(old_name, new_name);
Note: as argv[0] is the program name, this program changes it's own executable name to whatever the second argument is. If you want it to change another file's name, then you should use argv[0] and argv[1].
sizeof() returns the size of the type - ie the size of a pointer (probably 32bits) or a char (8bits)
To get the length of a string you need strlen()
Additionally in ansi C you can't create an array with a variable for the size. You can in the new C standard or for now you can use malloc() to create an array
argv is of the type char*[], i.e., an array of pointers to char. Thus, any first level element will simply be a char* and, as such, sizeof(argv[i]) will always return the native pointer size. You need to use strlen or some equivalent function to get the length of the string.
Related
Note: I can't use any libs or includes!
I have the following Code:
void twstng(char * str, int end, int strt) {
if(strt != end && strt != end-1) {
int hlp = str[strt];
printf("strt %d end %d hlp %d\n", strt, end, hlp);
str[strt] = str[end-1];
printf("test\n");
str[end-1] = hlp;
printf("test\n");
twstng(str, strt+1, end-1);
}
}
and in the main function:
char * sol = "hello";
twisting(sol, 5, 0);
I want to twist the entire string. But the console shows:
strt 0 end 4 help 104
And then comes a memory access error. But why?
My second problem is, that in the original task the given string is a
const char * const str
How can I work with it in the twstng function?
Your char *sol is a pointer to the string "hello". Being a string literal, it is actually read-only, and thus when you pass the pointer to your function, you get an error when you modify the contents of the constant string "hello" through the pointer.
Regarding the second part of the question, const char * const (i.e., constant pointer to a constant char) would indeed be a better type for the pointer, as it would convey that the thing pointed to is constant. However, then you cannot pass this pointer to the function (because the function takes a pointer to a non-const char), and it is not clear from the information given how you are "allowed" to work around this. One way is to copy the string and modify the copy.
edit: And as pointed out by other answers, your recursive call mixes up the start and end arguments (by using the more logical order of start first).
In C all string literals are read-only arrays of characters. It can be stored in memory that is not modifiable, leading to errors such as your when you attempt to modify it. That's why you should always use const char * when referring to string literals.
Use an array instead:
char sol[] = "hello";
I believe the recursive call to 'twstng()' at the bottom of the function has passed the new start and end indexes in the wrong order, given the names in the declaration (or else the declaration has them in the wrong order).
You mixed up your arguments.
Your function declaration says, that the first argument is the end and the second is the strt.
Your recursive call mixes them up.
To be clear, I'm not asking the difference between char *str and char str[]. I'm even more of a beginner than that. I'm implementing the following code:
// Convert long long to string
char number_str[];
sprintf(number_str, "%lld", number_ll);
When I run printf("%s\n", number_str);, it spits out the correct number, no matter if I put 2 or 256 between those brackets. Which leads me to ask, what are these brackets for?
I was exposed to char str[] in this post.
When I run printf("%s\n", number_str);, it spits out the correct number, no matter if I put 2 or 256 between those brackets. Which leads me to ask, what are these brackets for?
This is because your code invokes undefined behavior. You have not allocated space for your array.
What is the meaning of the value placed between the braces in char str[]?
It means that how much space do you want to allocate for your arrays. But note that when an initializer is used, this value, i.e, length of array (first dimension in case of multidimensional arrays) can be omitted.
In an array declaration, the number between the [ and ] specifies the number of elements in the array.
The code in your question:
char number_str[];
sprintf(number_str, "%lld", number_ll);
is illegal. If it appears inside a function definition, then you cannot use empty brackets; you must specify the size of the array -- and a call to sprintf, or to any other function, can only appear inside a function definition.
If you do specify the size of the array:
char number_str[100];
sprintf(number_str, "%lld", number_ll);
that creates an object number_str which is an array of 100 char elements. If you make the array too small:
char number_str[3];
sprintf(number_str, "%lld", number_ll); /* let's say number_ll == 12345 */
then your program may appear to work, but in fact its behavior is undefined. The sprintf call will attempt to store 6 characters in a 3-character array.
A C compiler is not obliged to diagnose this error. It will very likely let you try to do this, resulting in data being written into memory areas that you don't own.
At file scope, you can declare something like:
extern char array[];
which specifies that an object called array, of type array (of some unspecified size) of char is defined elsewhere.
As a (rather annoying) special case, a function parameter defined with the syntax of an array is actually a pointer:
void func(char param[42]) {
/* param is a pointer; the 42 is silently ignored */
}
Always remember that arrays and pointers are two different things. For an explanation of their admittedly confusing relationship, see section 6 of the comp.lang.c FAQ.
I have a program that asks to input two arguments using argv and I would like to then using the length of argv[1] and argv[2] dynamically allocate memory for two pointers to char inside my struct equal to the size of argv[1] and argv[2].
Here is my code but I'm not sure if I did it correctly, can anyone verify? Parameters passedargv1 and passedargv2 inside the function are argv[1] and argv[2] passed from the main() function. Basically I want to make chararray1=argv[1] and chararray2=argv[2] as if they were just plain char arrays, but I don't know ahead of time the size of our input so I can't pre-initialize chararray2 and chararray2. Also, I can't change what is inside argv, so i cannot have chararray1 and chararray2 just point to them because I will need to change them later on.
struct StructInformation{
char *chararray1;
char *chararray2;
};
typedef struct StructInformation SimplifiedStruct;
SimplifiedStruct *CreateMem(char *passedargv1, char *passedargv2) {
SimplifiedStruct *ptr=(SimplifiedStruct*)malloc(sizeof(SimplifiedStruct));
ptr->chararray1=(char*)malloc(sizeof(passedargv1));
ptr->chararray2=(char*)malloc(sizeof(passedargv2));
Don't cast the return from malloc()
malloc(char*)malloc is obviously wrong.
For your main issue, sizeof(passedargv1) and sizeof(passedargv2) both just evaluate to sizeof(char *), so no, you have not done it correctly. You'll need to call strlen() on your two arguments, and add 1 to each, that'll tell you how much memory you need to allocate, presuming you just want to copy in the strings.
For instance:
ptr->chararray1 = malloc(strlen(passedargv1) + 1);
ptr->chararray2 = malloc(strlen(passedargv2) + 1);
and then presumably:
strcpy(ptr->chararray1, passedargv1);
strcpy(ptr->chararray2, passedargv2);
Don't forget to check the return from malloc() to make sure you got your memory.
Replace sizeof with strlen and remember to include string.h. Because the size of a pointer always equals 4. And there is no need to use a cast when calling malloc.
ptr->chararray1 = malloc(strlen(passedargv1) + 1);
ptr->chararray2 = malloc(strlen(passedargv2) + 1);
EDIT:
Prototype of malloc:
void* malloc (size_t size);
It returns a pointer of void* which can be cast to the desired type of data pointer in order to be dereferenceable. Since you have already defined chararray1 and chararray2 as char*, casts can be omitted.
I'm trying to learn C and as a start, i set off writing a strcpy for my own practice. As we know, the original strcpy easily allows for security problems so I gave myself the task to write a "safe" strcpy.
The path I've chosen is to check wether the source string (character array) actually fits in the destination memory. As I've understood it, a string in C is nothing more than a pointer to a character array, 0x00 terminated.
So my challenge is how to find how much memory the compiler actually reserved for the destination string?
I tried:
sizeof(dest)
but that doesn't work, since it will return (as I later found out) the size of dest which is actually a pointer and on my 64 bit machine, will always return 8.
I also tried:
strlen(dest)
but that doesn't work either because it will just return the length until the first 0x0 is encountered, which doesn't necessarily reflect the actual memory reserved.
So this all sums up to the following question: How to find our how much memory the compiler reserved for my destination "string"???
Example:
char s[80] = "";
int i = someFunction(s); // should return 80
What is "someFunction"?
Thanks in advance!
Once you pass a char pointer to the function you are writing, you will loose knowledge for how much memory is allocated to s. You will need to pass this size as argument to the function.
You can use sizeof to check at compile time:
char s[80] = "";
int i = sizeof s ; // should return 80
Note that this fails if s is a pointer:
char *s = "";
int j = sizeof s; /* probably 4 or 8. */
Arrays are not pointers. To keep track of the size allocated for a pointer, the program simply must keep track of it. Also, you cannot pass an array to a function. When you use an array as an argument to a function, the compiler converts that to a pointer to the first element, so if you want the size to be avaliable to the called function, it must be passed as a parameter. For example:
char s[ SIZ ] = "";
foo( s, sizeof s );
So this all sums up to the following question: How to find our how much memory the compiler reserved for my destination "string"???
There is no portable way to find out how much memory is allocated. You have to keep track of it yourself.
The implementation must keep track of how much memory was malloced to a pointer, and it may make something available for you to find out. For example, glibc's malloc.h exposes
size_t malloc_usable_size (void *__ptr)
that gives you access to roughly that information, however, it doesn't tell you how much you requested, but how much is usable. Of course, that only works with pointers you obtained from malloc (and friends). For an array, you can only use sizeof where the array itself is in scope.
char s[80] = "";
int i = someFunction(s); // should return 80
In an expression s is a pointer to the first element of the array s. You cannot deduce the size of an array object with the only information of the value of a pointer to its first element. The only thing you can do is to store the information of the size of the array after you declare the array (here sizeof s) and then pass this information to the functions that need it.
There's no portable way to do it. However, the implementation certainly needs to know this information internally. Unix-based OSes, like Linux and OS X, provide functions for this task:
// OS X
#include <malloc/malloc.h>
size_t allocated = malloc_size(somePtr);
// Linux
#include <malloc.h>
size_t allocated = malloc_usable_size(somePtr);
// Maybe Windows...
size_t allocated = _msize(somePtr);
A way to tag the member returned by malloc is to always malloc an extra sizeof(size_t) bytes. Add that to the address malloc returns, and you have a storage space for storing the actual length. Store the malloced size - the sizeof (size_t) there, and you have the basis for your new set of functions.
When you pass two of these sorts of pointers into your new-special strcpy, you can subtract sizeof(size_t) off the pointers, and access the sizes directly. That lets you decide if the memory can be copied safely.
If you are doing strcat, then the two sizes, along with calculating the strlens means you can do the same sort of check to see if the results of the strcat will overflow the memory.
It's doable.
It's probably more trouble than it's worth.
Consider what happens if you pass in a character pointer that was not mallocated.
The assumption is that the size is before the pointer. That assumption is false.
Attempting to access the size in that case is undefined behavior. If you are lucky, you may get a signal.
One other implication of that sort of implementation is that when you go to free the memory, you have to pass in exactly-the-pointer-that-malloc-returned. If you don't get that right, heap corruption is possible.
Long story short...
Don't do it that way.
For situations where you are using character buffers in your program, you can do some smoke and mirrors to get the effect that you want. Something like this.
char input[] = "test";
char output[3];
if (sizeof(output) < sizeof(input))
{
memcpy(output,input,sizeof(input) + 1);
}
else
{
printf("Overflow detected value <%s>\n",input);
}
One can improve the error message by wraping the code in a macro.
#define STRCPYX(output,input) \
if (sizeof(output) < sizeof(input)) \
{ \
memcpy(output,input,sizeof(input) + 1); \
} \
else \
{ \
printf("STRCPYX would overflow %s with value <%s> from %s\n", \
#output, input, #input); \
} \
char input[] = "test";
char output[3];
STRCPYX(output,input);
While this does give you what you want, the same sort of risks apply.
char *input = "testing 123 testing";
char output[9];
STRCPYX(output,input);
the size of input is 8, and output is 9, the value of output ends up as "Testing "
C was not designed to protect the programmer from doing things incorrectly.
It is kind of like you are attempting to paddle upriver :)
It is a good exercise to think about.
Although arrays and pointers can appear to be interchangeable, they differ in one important aspect; an array has size. However because an array when passed to a function "degrades" to a pointer, the size information is lost.
The point is that at some point you know the size of the object - because you allocated it or declared it to be a certain size. The C language makes it your responsibility to retain and disseminate that information as necessary. So after your example:
char s[80] = ""; // sizeof(s) here is 80, because an array has size
int i = someFunction(s, sizeof(s)) ; // You have to tell the function how big the array is.
There is no "magic" method of determining the size of the array within someFunction(), because that information is discarded (for reasons of performance and efficiency - C is relatively low level in this respect, and does not add code or data that is not explicit); if the information is needed, you must explicitly pass it.
One way in which you can pass a string and retain size information, and even pass the string by copy rather than by reference is to wrap the string in a struct thus:
typedef struct
{
char s[80] ;
} charArray_t ;
then
charArray_t s ;
int i = someFunction( &s ) ;
with a definition of someFunction() like:
int someFunction( charArray_t* s )
{
return sizeof( s->s ) ;
}
You don't really gain much by doing that however - just avoid the additional parameter; in fact you loose some flexibility because someFunction() now only takes a fixed array length defined by charrArray_t, rather than any array. Sometimes such restrictions are useful. On feature of this approach is that you can pass by copy this:
int i = someFunction( s ) ;
then
int someFunction( charArray_t s )
{
return sizeof( s.s ) ;
}
since structures unlike arrays can be passed this way. You can equally return by copy as well. It can be somewhat inefficient however. Sometimes the convenience and safety outweigh the inefficiency however.
I've seen people's code as:
char *str = NULL;
and I've seen this is as well,
char *str;
I'm wonder, what is the proper way of initializing a string? and when are you supposed to initialize a string w/ and w/out NULL?
You're supposed to set it before using it. That's the only rule you have to follow to avoid undefined behaviour. Whether you initialise it at creation time or assign to it just before using it is not relevant.
Personally speaking, I prefer to never have variables set to unknown values myself so I'll usually do the first one unless it's set in close proximity (within a few lines).
In fact, with C99, where you don't have to declare locals at the tops of blocks any more, I'll generally defer creating it until it's needed, at which point it can be initialised as well.
Note that variables are given default values under certain circumstances (for example, if they're static storage duration such as being declared at file level, outside any function).
Local variables do not have this guarantee. So, if your second declaration above (char *str;) is inside a function, it may have rubbish in it and attempting to use it will invoke the afore-mentioned, dreaded, undefined behaviour.
The relevant part of the C99 standard 6.7.8/10:
If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate. If an object that has static storage duration is not initialized explicitly, then:
if it has pointer type, it is initialized to a null pointer;
if it has arithmetic type, it is initialized to (positive or unsigned) zero;
if it is an aggregate, every member is initialized (recursively) according to these rules;
if it is a union, the first named member is initialized (recursively) according to these rules.
I'm wonder, what is the proper way of initializing a string?
Well, since the second snippet defines an uninitialized pointer to string, I'd say the first one. :)
In general, if you want to play it safe, it's good to initialize to NULL all pointers; in this way, it's easy to spot problems derived from uninitialized pointers, since dereferencing a NULL pointer will yield a crash (actually, as far as the standard is concerned, it's undefined behavior, but on every machine I've seen it's a crash).
However, you should not confuse a NULL pointer to string with an empty string: a NULL pointer to string means that that pointer points to nothing, while an empty string is a "real", zero-length string (i.e. it contains just a NUL character).
char * str=NULL; /* NULL pointer to string - there's no string, just a pointer */
const char * str2 = ""; /* Pointer to a constant empty string */
char str3[] = "random text to reach 15 characters ;)"; /* String allocated (presumably on the stack) that contains some text */
*str3 = 0; /* str3 is emptied by putting a NUL in first position */
this is a general question about c variables not just char ptrs.
It is considered best practice to initialize a variable at the point of declaration. ie
char *str = NULL;
is a Good Thing. THis way you never have variables with unknown values. For example if later in your code you do
if(str != NULL)
doBar(str);
What will happen. str is in an unknown (and almost certainly not NULL) state
Note that static variables will be initialized to zero / NULL for you. Its not clear from the question if you are asking about locals or statics
Global variables are initialized with default values by a compiler, but local variables must be initialized.
an unitialized pointer should be considered as undefined so to avoid generating errors by using an undefined value it's always better to use
char *str = NULL;
also because
char *str;
this will be just an unallocated pointer to somewhere that will mostly cause problems when used if you forget to allocate it, you will need to allocate it ANYWAY (or copy another pointer).
This means that you can choose:
if you know that you will allocate it shortly after its declaration you can avoid setting it as NULL (this is a sort of rule to thumb)
in any other case, if you want to be sure, just do it. The only real problem occurs if you try to use it without having initialized it.
It depends entirely on how you're going to use it. In the following, it makes more sense not to initialize the variable:
int count;
while ((count = function()) > 0)
{
}
Don't initialise all your pointer variables to NULL on declaration "just in case".
The compiler will warn you if you try to use a pointer variable that has not been initialised, except when you pass it by address to a function (and you usually do that in order to give it a value).
Initialising a pointer to NULL is not the same as initialising it to a sensible value, and initialising it to NULL just disables the compiler's ability to tell you that you haven't initialised it to a sensible value.
Only initialise pointers to NULL on declaration if you get a compiler warning if you don't, or you are passing them by address to a function that expects them to be NULL.
If you can't see both the declaration of a pointer variable and the point at which it is first given a value in the same screen-full, your function is too big.
static const char str[] = "str";
or
static char str[] = "str";
Because free() doesn't do anything if you pass it a NULL value you can simplify your program like this:
char *str = NULL;
if ( somethingorother() )
{
str = malloc ( 100 );
if ( NULL == str )
goto error;
}
...
error:
cleanup();
free ( str );
If for some reason somethingorother() returns 0, if you haven't initialized str you will
free some random address anywhere possibly causing a failure.
I apologize for the use of goto, I know some finds it offensive. :)
Your first snippet is a variable definition with initialization; the second snippet is a variable definition without initialization.
The proper way to initialize a string is to provide an initializer when you define it. Initializing it to NULL or something else depends on what you want to do with it.
Also be aware of what you call "string". C has no such type: usually "string" in a C context means "array of [some number of] char". You have pointers to char in the snippets above.
Assume you have a program that wants the username in argv[1] and copies it to the string "name". When you define the name variable you can keep it uninitialized, or initialize it to NULL (if it's a pointer to char), or initialize with a default name.
int main(int argc, char **argv) {
char name_uninit[100];
char *name_ptr = NULL;
char name_default[100] = "anonymous";
if (argc > 1) {
strcpy(name_uninit, argv[1]); /* beware buffer overflow */
name_ptr = argv[1];
strcpy(name_default, argv[1]); /* beware buffer overflow */
}
/* ... */
/* name_uninit may be unusable (and untestable) if there were no command line parameters */
/* name_ptr may be NULL, but you can test for NULL */
/* name_default is a definite name */
}
By proper you mean bug free? well, it depends on the situation. But there are some rules of thumb I can recommend.
Firstly, note that strings in C are not like strings in other languages.
They are pointers to a block of characters. The end of which is terminated with a 0 byte or NULL terminator. hence null terminated string.
So for example, if you're going to do something like this:
char* str;
gets(str);
or interact with str in any way, then it's a monumental bug. The reason is because as I have just said, in C strings are not strings like other languages. They are just pointers. char* str is the size of a pointer and will always be.
Therefore, what you need to do is allocate some memory to hold a string.
/* this allocates 100 characters for a string
(including the null), remember to free it with free() */
char* str = (char*)malloc(100);
str[0] = 0;
/* so does this, automatically freed when it goes out of scope */
char str[100] = "";
However, sometimes all you need is a pointer.
e.g.
/* This declares the string (not intialized) */
char* str;
/* use the string from earlier and assign the allocated/copied
buffer to our variable */
str = strdup(other_string);
In general, it really depends on how you expect to use the string pointer.
My recommendation is to either use the fixed size array form if you're only going to be using it in the scope of that function and the string is relatively small. Or initialize it to NULL. Then you can explicitly test for NULL string which is useful when it's passed into a function.
Beware that using the array form can also be a problem if you use a function that simply checks for NULL as to where the end of the string is. e.g. strcpy or strcat functions don't care how big your buffer is. Therefore consider using an alternative like BSD's strlcpy & strlcat. Or strcpy_s & strcat_s (windows).
Many functions expect you to pass in a proper address as well. So again, be aware that
char* str = NULL;
strcmp(str, "Hello World");
will crash big time because strcmp doesn't like having NULL passed in.
You have tagged this as C, but if anyone is using C++ and reads this question then switch to using std::string where possible and use the .c_str() member function on the string where you need to interact with an API that requires a standard null terminated c string.