warning: assignment makes integer from pointer without a cast ARGV - c

This is the warning I get.
copyit.c: In function ‘main’:
copyit.c:15: warning: assignment makes integer from pointer without a cast
copyit.c:16: warning: assignment makes integer from pointer without a cast
The lines of code that this corresponds to are the ones that begin with pointers (*).
char source[128],target[128],buffer[512];
if(argc==3) {
*source = argv[1];
*target = argv[2];
}
I just want to assign those two things so I can pass them from the command line like that and I can then use them in my handle (ex: inhandle=open(source,O_RDONLY);
Thank you.

argv is an array of string pointers. You should just change source and target to char * or const char * instead of arrays and change the code to
source = argv[3];
target = argv[4];
That will make it work. It will also prevent a buffer overflow had you copied the strings into the arrays. It would also mean your app will handle long file paths.

Use strcpy() from string.h:
strcpy(source,argv[1]);
strcpy(target,argv[2]);

Related

Why we didn't use * during dereferencing the pointer?

In the below code, we get a pointer from strdup(source) and we store it in a pointer named target.
Now, when we print the string using pointer, we don't add * at the beginning of the pointer: why is it so? As I studied whenever we want to dereference any pointer we use *pointer_name. If we add * in the below code, we get an error.
I am very beginner, so pls ans in easy words.
#include<stdio.h>
#include<string.h>
int main()
{
char source[] = "Programming";
char* target = strdup(source);
printf("%s\n",target);
return 0;
}
printf expects a char pointer in the place of the %s specifier.
https://en.cppreference.com/w/c/io/fprintf
char* target = strdup(source);
printf("%s\n",target);
Why we don't use *target in the code above?
The explanation is quite simple, as already stated in previous answers: target has type char pointer, which is exactly what printf() wants in the above call.
Now, printf() is a little complicated because its semantic is not simple - basically it accepts zero or more arguments after the first, of any type (possibly applying promotion). But if we use strdup() again, maybe it is simpler:
char* target2 = strdup(target);
Here, if you wrote strdup(*target), the compiler might warn that you are passing a char instead of a pointer to char.
strdup() returns a char*, hence the char* type of target. target holds a pointer to the first character in an array of chars. printf("%s", string) expects string to be a char*, so there’s no reason to do anything to target; just pass it to printf().
If you dereferenced target, you would get a single char (P in this case). printf() would then complain that you had supplied a character instead of a string (pointer to character). Even worse, the program could compile, and then printf() would try to print the string at address P (0x50), which would result in probably unwanted behaviour.
When working with arrays—a string is a type of array—you rarely want to dereference the array.

add string to given command line argument in C

Hello i just started to programm in C and i am trying to read a file and give the file name as argument without the ending .txt . I want to add .txt in my code : ./myexample.exe file
if i use file.txt there is no problem but i dont know how to change argv[1]
i tried char *n = argv[1] + ".txt"; it doesnt works and i dont know anything else..
int main(int argc, char* argv[]) {
char *n = argv[1] +".txt";
FILE *fp1;
fp1 = fopen(n , "r");
Thats what i get if i use char *n = argv[1]+".txt"
error: invalid operands to binary + (have 'char *' and 'char *')
In your code,
char *n = argv[1] +".txt";
does not do what you think it does. In C, the + cannot be used to concatenate strings.
FYI, from C11, chapter §6.5.6
For addition, either both operands shall have arithmetic type, or one operand shall be a
pointer to a complete object type and the other shall have integer type. (Incrementing is
equivalent to adding 1.)
Both the operands cannot be of pointer-to-object type.
If you meant to concatenate strings, use strcat() but make sure
the destination is modifiable (attempt to modify string literal is UB)
the destination got enough space to contain the final result (shorter destination lead to access out of bound memory invoking UB, again).
You can't concatenate strings with +. Use strcpy and strcat:
char n[256];
strcpy(n, argv[1]);
strcat(n, ".txt");
Make sure that n is large enough to hold the filename + extension.
This is kind of annoying to do safely: you need to be careful to make a big enough char array to hold the whole string. One way:
size_t arglen=strlen(argv[1]);
char* filename=malloc(arglen+5); //Enough to hold the whole string
strcpy(filename,argv[1]);
strcat(filename,".txt");
Be sure to free the pointer later.

What does (char* ) do in C?

What does (char* )str do in the below code?
/**
* Main file
*/
#include <assert.h>
#include <mylib.h>
int main()
{
const char str[] = "this is my first lab\n";
int ret=1;
ret = my_print((char *)str, sizeof(str));
assert(!ret);
return 0;
}
This code is written by my instructor.
my_print is a function which receives a pointer to a string and the size of that string. I am confused on why do we have to use (char *)str to pass the string to the my_print function. What does it actually do?
It casts away the const.
This means it makes your program likely to crash in case my_print modifies that string since its memory may be marked as read-only. So it's generally a bad idea to remove the const modifier through a cast.
In your case it looks a bit like whoever implemented my_print didn't think that string to be printed would never have to be modified and thus didn't make it accept a const char * argument.
So what you should do instead of the cast is changing the definition of my_print to accept a const char * instead of a char * as its first parameter.
That is "type casting" (or "type conversion"). In other words, it tells the compiler to treat one type as another type.
What this specific conversion does is tell the compiler to treat the constant string as not constant. If the called function tries to modify the string, it may not work, or may even crash the program, as modifying constant data is undefined behavior.
It is a typecast, i.e. it changes the datatype. (char*) means type cast to type "pointer to char"

When are values implicitly converted to pointers?

I have many functions like:
void write(char* param, int len)
{
//
}
And I notice that I almost never use the & operator for arguments. When I pass an array:
char in[20];
write(in, 20);
I dont need it, but when I pass a single value:
write(5, 1);
I don't seem to need it, and when I pass a pointer:
char* in = malloc(20);
write(in, 20);
I also dont need it. So in which circumstances do I actually need to call:
write(&in, 1);
Because I'm confused :D
Are you sure about your second case? It doesn't compile for me and should be
char in = 5;
write(&in, 1);
When are values implicitly converted to pointers?
In practice, integer types may be converted to pointers implicitly by the compiler. In theory, this is illegal and compilers that accept it will usually issue a warning:
example.c:2:6: warning: incompatible integer to pointer conversion initializing
'void *' with an expression of type 'int'
In your above example:
char in = 5;
write(in, 20);
char is an integer type, so if your compiler allows it, it may be implicitly converted to a pointer type, although it is not part of the C standard and is completely compiler-specific.
Note that converting an integer type to a pointer type using a cast is allowed by the standard, although results are implementation-defined:
char in = 5;
write((char *)in, 20);
The only allowed case of implicit conversion is when integer constant 0, which denotes a null pointer:
write(0, 20); // allowed
Note that the integer constant is itself allowed, but a variable of integer type with the value 0 is not:
char in = 0;
write(in, 20); // not allowed
As for the others, when you pass a pointer, you don't need the &, obviously, because it's already a pointer. When you pass an array, it decays to a pointer so you don't need & there either. In both these cases it would be actually illegal to use it, as your function above expects a char * and be fed with a char ** and a char (*)[20] respectively.
If you copy somehow the prototype of function 'write' to the file where you call this function, as follows.
void write(char *in, int len);
void foo(int bar){
char in=5;
write(in, 1);
}
You will probably get a warning. Because in is not a pointer, though 5 can be an address.
I guess if your program is compiled and linked successfully, it will crash at run-time.
with using;
return_type function_name(prim_data_type* param...)
param is a pointer that pointing an address in the memory and *param is the value in that address.
Answer is about what you want to do with this param.
char in[20];
by saying that "in" is the first element's address. So at the function call:
write(in, 20);
you are sending the first element's address so in the function implementation, you can access the first element by *param, second element with *(param+1) or param[1] etc.
The place that you are confused is here:
char in = 5;
write(in, 1);
Because in is the address 5 (00000005), so in the implementation of the function you are accessing that place whichever value is there. You must be careful with using like this.
In the malloc operation:
char* in = malloc(20);
write(in, 20);
in is a pointer to an address (first element's address) holding up 20 elements of char can be take space. In the function you can access to all elements with param pointer(*param is the first element, *(param+7) or param[7] is the 8. element)
In the conclusion, when you want to play with an primary data typed variable (int, float, char..) in another function, you must use;
write(&in);
By doing that, in the implementation of that write function, you can access that variable, change the value by *param with no confusion.
Note:Some explanations were simplified here for better understanding. Extra warnings would be welcomed here.
Functions and arrays decay into pointers in some contexts. Functions can decay into pointers to functions, and arrays can decay into a pointer to the first element of the array. No other types behave this way.
This example:
char in = 5;
write(in, 1);
Is wrong though. You definitely need the & in that case. Are you sure it worked like that?

Extracting string from main() arguments

I am trying to create a pointer to one of the main() arguments in my program.
I set up the initial pointer, then I set it equal to the 2nd element in the array, but I get an error when I try to compile, segmentation fault. Does this occur because a pointer is pointing to a bad address?
Here is the code:
char *filename;
*filename = argv[1];
printf("The filename is: %s", *filename);
I get errors about the pointer trying to cast the argument as an int. Is this because the pointer is actually an integer address value and I am trying to set it equal to a string?
Edit: When I change to "filename = argv[1]", then I get the following error from my compiler: assignment discards qualifiers from pointer target type.
A segmentation fault couldn't possibly occur when you compile. Unless, well, the compiler violates memory safety, which is unlikely. I'll take it that it happens when you run the program :D.
The problem is here:
*filename = argv[1];
It should be:
filename = argv[1];
Why? You declared a pointer to char, unitialized, poiting nowhere in particular. Then, you dereferenced that pointer and assigned data to that memory position. Which is, well, who knows where!
Edit: you also dereference filename in the printf() call. Remove that * :).
Also, didnt' the compiler shoot a warning when you assigned *filename? Making integer from pointer without a cast, would be my guess? Pay attention to the warnings, they provide useful information!
Cheers.
You're not making filename point to the same place as argv[1]. To do that you need
filename = argv[1];
With your version (*filename = argv[1];) you're trying to make whatever filename points to have the value that is in argv[1]. There's lots of stuff wrong with this: a) filename is not initialized and can point anywhere, even invalid locations; b) argv[1] is of type char* and you're trying to put it into a location of type char!
In the statement *filename = argv[1];, the expression *filename attempts to dereference (find the value pointed to) the filename pointer, which is not yet pointing anywhere meaningful.
Change the assignment to filename = argv[1].
You're dereferencing the char* when you try to assign it, so you're trying to stuff a pointer into a char. And since filename is uninitialized, you're trying to hit some random address (or perhaps address 0x00000000. And your print statement, if you got that far, wouldn't work either: you're again dereferencing the char* (to get a char) and then telling printf to interpret that as a pointer to a nul-terminated string.
Try this:
char *filename ;
filename = argv[1] ;
printf( "The filename is: %s" , filename ) ;

Resources