I wrote three ways of passing arguments to a function that accepts argv argument.
The first method of using string literals is the shortest and works fine, but gives me a deprecated warning as my test harness is cpp based:
error: conversion
from string literal to 'char *' is deprecated
[-Werror,-Wc++11-compat-deprecated-writable-strings]
The method using malloc works, though it's a tad bit longer.
The last method causes a seg fault. Can you help me figure out the mistake in the third method, where I create an array with predefined size and copy the contents? Why does it fail?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TEST3
int console_tester(int argc, char *argv[])
{
printf("argv: %s\n", argv[0]);
return 0;
}
int main()
{
#ifdef TEST1
// works, shortest, but gives compilation warnings
char *test_cmd[2] = {"hello1", "hello2"};
int result = console_tester(2, (char**)test_cmd);
#endif
// works, verbose
#ifdef TEST2
char *test_cmd[2];
test_cmd[0] = malloc(10);
test_cmd[1] = malloc(10);
memset(test_cmd[0], 0, 10);
memset(test_cmd[0], 1, 10);
memcpy(test_cmd[0], "hello1", sizeof("hello1"));
memcpy(test_cmd[1], "hello2", sizeof("hello2"));
int result = console_tester(2, (char**)test_cmd);
free(test_cmd[0]);
free(test_cmd[1]);
#endif
// crash and burn
#ifdef TEST3
char test_cmd[2][10];
memset(&test_cmd[0], 0, 10);
memset(&test_cmd[1], 0, 10);
memcpy(&test_cmd[0], "hello1", sizeof("hello1"));
memcpy(&test_cmd[1], "hello2", sizeof("hello2"));
int result = console_tester(2, (char**)test_cmd);
#endif
return 0;
}
In the third example you're doing an invalid conversion:
char test_cmd[2][10];
memset(&test_cmd[0], 0, 10);
memset(&test_cmd[1], 0, 10);
memcpy(&test_cmd[0], "hello1", sizeof("hello1"));
memcpy(&test_cmd[1], "hello2", sizeof("hello2"));
int result = console_tester(2, (char**)test_cmd);
This produces a compiler warning for me when I strip off the (char**) brute-force casting:
warning: incompatible pointer types passing 'char (*)[10]' to parameter of type 'char **' [-Wincompatible-pointer-types]
Which really should be an error. You can't switch those arbitrarily. You don't have the right kind of structure to pass in, so you must convert it to the correct structure first.
The other two examples both use char** properly so they're fine.
This is why turning on all warnings your compiler has to offer can help narrow down problems quickly. C, and by extension C++, really does not care if you're asking to do something invalid, it'll do it if told to do it, and then crash or act really strange because of it.
Related
Inside a thread, I run this function:
char *r = NetString("ch","aaaaa");
printf("%s",r); printf("%s","\n");
Which calls
char *NetString(char *id, char *data) {
char *result;
result = (char *)malloc(strlen(id)+strlen(data)+2);
strcpy(result, id);
strcat(result, "/");
strcat(result, data);
printf("%s",result); printf("%s","\n");
return (char *)result;
}
In the console, when I compile this warning shows up:
warning: initialization makes pointer from integer without a cast
[enabled by default]: char *r = NetString("ch","aaaaa");
^
If you need the full code (which may be a bit unorganized), here it is:
pastebin
Apparently, this code runs as expected (returns "ch/aaaaa" twice) when not run in a thread, but when I run it in a thread, the string only prints once (that is, in the NetString function). Any help? Thanks a lot.
This code
char *r = NetString("ch","aaaaa");
and this error
warning: initialization makes pointer from integer without a cast
[enabled by default]: char *r = NetString("ch","aaaaa");
^
almost certainly mean:
You are calling NetString() without providing a function prototype, thus it is treated as returning int.
You are running on a 64-bit platform where pointers are 64 bit and int values are 32 bit.
Thus, your char * pointer value from NetString() gets truncated to an int, then assigned to a pointer, where it no longer points to anything useful.
You need to provide a proper prototype with a function declaration:
char *NetString( char *, char * );
in all code that calls NetString(), and the prototype needs to be before any such calls.
#include <stdio.h>
#include <string.h>
int myprint(char_array){
char mystring[80];
strcat(mystring, "\n");
printf("%s", mystring);
return 0;
}
int main(int argc, char** argv){
int count = 5;
char letter = 'c';
printf("decimal: %d, char: %c\n", count, letter);
myprint("sup");
return 0;
}
I get warnings on compile:
cchilders:~/projects/buildyourownlisp_in_C/ch3 [master]$ compile basics.c basics
basics.c: In function ‘myprint’:
basics.c:4:5: warning: type of ‘char_array’ defaults to ‘int’
int myprint(char_array){
^
It compiles, but my myprint function doesn't work:
cchilders:~/projects/buildyourownlisp_in_C/ch3 [master]$ ./basics
decimal: 5, char: c
I see this answer warning: return type defaults to ‘int’ [-Wreturn-type] but doesn't apply to me since I did declare int main(...)
I also see this declaration of functions:
return_type function_name( parameter list ) {
body of the function
}
And for myprint I declare as taking int and return 0. What does this warning mean and why doesn't my function work? Thank you
ANSWER:
void myprint(char mystring[]){
strcat(mystring, "\n");
printf("%s", mystring);
}
quiets the warnings, but causes Segmentation fault (core dumped)
Changing to
void myprint(char[] mystring){
strcat(mystring, "\n");
printf("%s", mystring);
}
makes it worse:
cchilders:~/projects/buildyourownlisp_in_C/ch3 [master]$ cc -std=c99 -Wall basics.c -o basics
basics.c:4:21: error: expected ‘;’, ‘,’ or ‘)’ before ‘mystring’
void myprint(char[] mystring;){
^
basics.c: In function ‘main’:
basics.c:15:5: warning: implicit declaration of function ‘myprint’ [-Wimplicit-function-declaration]
myprint("sup");
^
I also tried
void myprint(char[] mystring;){...
and
void myprint(char[] mystring,){...
As others have pointed out, you didn't specify a type for char_array, so it is assumed to be int. Changing it to char char_array[] fixes this.
Your other problem is that you're passing a string constant ("sup") to this function and are then attempting to modify it. String constants are stored in a read-only section of memory, so you can't modify it.
Given that you're only printing the string with a newline, you can do this instead:
void myprint(char mystring[]){
printf("%s\n", mystring);
}
You are not providing a data type for char_array in
int myprint(char_array)
You need char * or whatever you want it to be.
Firstly, function definitions should be like
return-type function-name ( parameter-type parameter-name, parameter-type parameter-name)
{ ... }
You did not specify either a parameter type or a parameter name. If you mean char_array to mean a type, you need to define it first, using a typedef or a struct or something else. If you mean char_array to be a parameter name, you need to specify its type, as
char[] char_array
say. Also, in this case, you do not actually use the variable char array anywhere in the function myprint. So the argument "sup" is not being used at all.
After edit to the question:
Try
char str[] = "sup";
myprint(str);
instead. As far as I know, you can't pass a string (a character array) by value.
int myprint(char_array)
What type has the parameter with name char_array? Because you didn't specify it, the compiler assumed it to be an int. Luckily it's warning you about that.
Don't rely on such behaviour, though. (I don't know whether this is still legal in C11 for example) Just write correct function declarations, including parameter types.
You need to specify the type of the parameters you expect to be passed to the function. There are mistakes in the function too. char_array is of char* type. You need to copy every part of the passed array to your local array, THEN only can you call printf for this function to work
I'm new to the world of C programming, and I as trying to code a primitive, terminal-based version of the "Hangman" game.
One of the steps doing this (or at least the way I am working on), is to create a second char array (next to the original char array that stores the word one needs to guess), filled with "*" for every Char of the original array, and display it. Although the rest of the programming part is not there yet (since I am not finished with it yet), I doubt it is relevant for now (however I allready know how to proceed, that is if I weren't bothered by some error-messages)....
Here's the code I have so far:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
void hiddenArray(char array[]);
char *secretWord;
char *arrayCover;
char letter;
int main(int argc, char *argv[]){
secretWord = "Test";
printf("Welcome to the Hangman!\n\n");
hiddenArray(secretWord);
printf("What is the hidden Word?: %c\n", *arrayCover);
printf("Guess a letter\n");
scanf("%c", &letter);
}
void hiddenArray(char array[]){
int size,i;
size = sizeof(*array);
for (i=0;i<size-1;i++){
*(arrayCover+i) = "*";
}
}
Now I have two issues... the first one:
I don't understand the error message I am getting after compilation:
pendu.c:41:19: warning: incompatible pointer to integer conversion assigning to 'char' from 'char [2]' [-Wint-conversion]
*(arrayCover+i) = "*";
^ ~~~
1 warning generated.
And my second question: the second Array created, filled with "*" is not being displayed, what did I do wrong?
I'd love for some help, cheers!
Your program have some errors to be corrected .
1) Your *arraycover is pointing to some unknown value, You have not initialized it.
2) sizeof(*array) should be sizeof(array)
3) *(arrayCover+i) = "*" should be *(arrayCover+i) = '*';
I suggest you not to create too many global variables when you dont really need them
Create char secretWord[100] = "Test" instead of char *secretWord
Try this
size = sizeof(arrayCover)/sizeof(char);
for (i=0;i<size-1;i++){
*(array+i) = '*';
}
Despite of all these, I think you need to allocate memory for arrayCover
arrayCover = malloc(sizeof(char) * number_of_elements);
"*" is a string. Use '*' instead to get the char.
"*" is a string which also contains \0 also, resulting to 2 characters. Instead use '*' which is just a character.
The function hiddenArray has the formal argument array which need to be used locally instead of arrayCover as below,
void hiddenArray(char array[]){
int size,i;
size = sizeof(array)/sizeof(array[0]);
for (i=0;i<size-1;i++){
*(array+i) = '*'; /* Or array[i] = '*' */
}
}
This question already has answers here:
Passing two-dimensional array via pointer
(9 answers)
Closed 9 years ago.
I am trying to make function that fills array of strings with lines from file, but the compiler (GCC) still giving me a warning. Than if I try to run compiled app, it gives me "Segmentation fault" error
Source code:
main
#include <stdio.h>
#include "getAdresses.h"
int main(int argc, char **argv){
char adresses[1024][128];
getAdresses(adresses);
printf("%s", adresses[1]);
}
getAdresses
include <stdio.h>
int getAdresses(char **adresses){
FILE *fr;
fr = fopen("adresses", "r");
int i = 0;
while(adresses[i-1][0] != EOF){
fscanf(fr, "%s\n", &adresses[i]);
i++;
}
}
It's giving me this error:
main.c: In function ‘main’:
main.c:9:2: warning: passing argument 1 of ‘getAdresses’ from incompatible pointer type [enabled by default]
In file included from main.c:3:0:
getAdresses.h:1:5: note: expected ‘char **’ but argument is of type ‘char (*)[128]’
First of all you have done the typical mistake: char ** is not the same as a char (*)[128]. The latter is the type of adresses.
You get the segmentation fault when you try to dereference it in line
while(adresses[i-1][0] != EOF)
Aside from the fact that adressing [i-1] for i = 0 will give you bad results you should define your function as
int getAdresses(char (*adresses)[128])
to be able to pass your two dimensional array correctly and fscanf should scan into your actual line buffer and if you are reading line by line use fgets:
while(fgets(adresses[i], 128, fr)) i++;
when you pass adresses[1024][128] to a function, the compiler will only do one step of decay, and the parameter type should be char (*)[128] instead of char ** .
You also need to pass its first dimension to the function, which means
int getAdresses(char (int (*arr)[128], int x)
check the c-faq for a detailed explanation for this issue.
The array you allocated declaring
char adresses[1024][128]
is actually a char* (it isn't but it's much closer to it than to char**).
The double diemension accessor is actually just a syntactic sugar for [x+y*width].
To pass the array as a parameter use:
int getAdresses(char (*adresses)[128])
My goal is to convert a string such as "A1234" to a long with value 1234. My first step was to just convert "1234" to a long, and that works as expected:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
char* test = "1234";
long val = strtol(test,NULL,10);
char output[20];
sprintf(output,"Value: %Ld",val);
printf("%s\r\n",output);
return 0;
}
Now I am having trouble with pointers and trying to ignore the A at the beginning of the string. I have tried char* test = "A1234"; long val = strtol(test[1],NULL,10); however that crashes the program.
How do I set this up properly to get it pointing to the correct spot?
You are almost right. You need to pass a pointer to strtol, though:
long val = strtol(&test[1], NULL, 10);
or
long val = strtol(test + 1, NULL, 10);
Turning on some compiler warning flags would have told you your problem. For example, from clang (even with no special flags added):
example.c:6:23: warning: incompatible integer to pointer conversion passing
'char' to parameter of type 'const char *'; take the address with &
[-Wint-conversion]
long val = strtol(test[1],NULL,10);
^~~~~~~
&
/usr/include/stdlib.h:181:26: note: passing argument to parameter here
long strtol(const char *, char **, int);
^
1 warning generated.
and from GCC:
example.c: In function ‘main’:
example.c:6: warning: passing argument 1 of ‘strtol’ makes pointer from integer
without a cast
Editorial note: I think you can see from these error messages why beginners are often well-advised to use clang rather than GCC.