I have a function:
int get_symbol(tab *tp, FILE *fp, char delim)
and I call it like this:
get_symbol(tp, fp, ';')
I always have it declared in the header as:
int get_symbol(tab *, FILE *, char);
No this all works fine, I can execute the code in the function and the delim is set.
But if I try to add one more char to the function's signature like:
int get_symbol(tab *tp, FILE *fp, char delim1, char delim2)
The function stops executing. Why would that be?
You should have :
int get_symbol(tab *tp, FILE *fp, char delim1, char delim2)
{
blah blah;
return 1;
}
...
...
get_symbol(tp, fp, ';','?')
do You?
OK, there's not enough information here, so I'm going to make a wild stab at an answer.
You're using a C++ compiler, and don't have warning levels set very high. You've changed the prototype for the function, but you've not changed the arguments when you call it. The C++ compiler is treating these as different functions due to overloading, and so is not calling the right one.
This may be way off what's happening. If it is, give us something more to go on….
As a guess at what "stops executing" could mean, did you update the signature in the header file as well?
Related
This is my .h file
#ifndef _test_h_
#define _test_h_
void new_cmd(void);
void open_cmd(void);
void close_cmd(void);
void close_all_cmd(void);
void save_cmd(void);
void save_as_cmd(void);
void save_all_cmd(void);
void print_cmd(void);
void exit_cmd(void);
void call(char *cmd_name);
struct {
char *cmd_name;
void (*cmd_pointer)(void);
} file_cmd[] =
{
{"new", new_cmd},
{"open", open_cmd},
{"close", close_cmd},
{"save", save_cmd},
{"save as", save_as_cmd},
{"save all", save_all_cmd},
{"print", print_cmd},
{"exit", exit_cmd}};
#endif
This is my function file
void call(char *cmd_name){
int i;
scanf("Enter command: %c\n",cmd_name);
for(i = 0; i < sizeof(file_cmd); i++){
if(strcmp(cmd_name, file_cmd[i].cmd_name) == 0){
file_cmd[i].cmd_pointer();
}
}
I just deleted all file_cmd functions because it seems for other people
and this is my main file
#include <stdio.h>
#include <string.h>
#include "test.h"
int main(void){
char cmd;
call(cmd);
return 0;
}
More I want to know is that my function void call is correctly written.
when I try to compile, it says
expected 'char*' but argument is of type 'char'
multiple definition of 'file_cmd'
first define here.
I am so confused how to fix it.
Please help
thank you.
You have two very different errors that you really should have asked about in two different question, but I'll be nice and answer both anyway.
In the main function you have a variable named cmd. It is of type char. You pass it to the call function, which expects an argument of type char * (i.e. a null-terminated string).
To fix this you first need to make sure that cmd is the correct type (i.e. char * instead of plain char). Secondly you need to make sure this pointer is actually pointing to a valid null-terminated byte string.
In other words, something like this:
char *cmd = "open";
call(cmd);
C really only cares about translation units. A translation unit is a single source files with all included header files.
The problem here is that variables can only be defined in a single translation unit. And since you define the variable file_cmd in a header file that is included in multiple source files, it will be defined in both translation units created from those two source files.
The solution here is to only declare the variable in the header file, and define it in a single source file.
For example, do something like this in the header file
struct command_struct
{
char *cmd_name;
void (*cmd_pointer)(void);
};
extern struct command_struct file_cmd[];
Then in one source file (like your "function file")
struct command_struct file_cmd[] = {
// Your initialization...
};
There are also other problems with your code, some of them will lead to undefined behavior.
For example the sizeof operator returns the size in bytes, not the number of elements in an array. To get the number of elements in an array you need to divide the byte-size of the full array with the byte-size of a single element. For example sizeof file_cmd / file_cmd[0].
Do note that the division only works for real arrays, not pointers, and that arrays very easily decays to pointers (to their first element).
So usually I would declare any function pointer like this:
typedef size_t (*hash_function)(const int *);
and then later use it in another function
HashTable *hash_table_create(const hash_function hash)
so for any function which fulfills the hash_function definition like
size_t hash_modulo(const int *parameters)
size_t hash_universal(const int *parameters)
...
I can use them as a parameter
hash_table_create(hash_modulo)
The problem is: My IDE (Clion) complains that the parameters in this case do not match (the code works tho). Specifically it doesn't seem to accept passing hash_function as a parameter type, but will accept if I use size_t (*hash_function)(const int *) instead. What am I missing here?
Is my code right and my IDE wrong or vice versa?
Thanks in advance!
Edit 1: The exact error message is: Types 'hash_function' and size_t(const int *)' are not compatible
Edit 2: This seems to be a Clion Bug
CLion seems to have a bug (possibly). The function names are of the type size_t(const int *). Now, since functions are implicitly convertible to function pointers, your code is perfectly valid C.
The CLion syntax checker probably doesn't take implicit conversions into account. If you obtain a function pointer explicitly from the function name the error should go away:
hash_table_create(&hash_modulo); // Note the ampersand
I think the problem is that you typedef the function as const
HashTable *hash_table_create(const hash_function hash)
and the other functions you want to put in as parameters aren't declared const
size_t hash_modulo(const int *parameters)
size_t hash_universal(const int *parameters)
Edit:
This works fine in CodeBlocks
Change this:
size_t hash_modulo(const int *parameters)
size_t hash_universal(const int *parameters)
into this:
hash_function hash_modulo;
hash_function hash_universal;
and then this work fine:
hash_table_create(hash_modulo);
hash_table_create(hash_universal);
Explanation in the comment below.
Is there any possible methods to write a C program without including stdio.h as a header file. It was suggested that it can be implemented by declaring extern int scanf(char* format, ...);
#include <stdio.h> //I want this same code to work without including this line
int main ()
{
char str [80];
scanf ("%s",str);
return 0;
}
You can declare the scanf function with:
extern int scanf(const char *format, ...);
The extern keyword is optional but I like to include it as a reminder of the fact that the function is defined elsewhere.
Your example would then look like:
extern int scanf(const char *format, ...);
int main ()
{
char str [80];
scanf ("%s",str);
return 0;
}
In C-89, that code would compile without the #include, as function prototypes are optional.
Having said which, it comes under the list of 'really bad things to do' - scanf may be a macro, it might have one or more required parameters, ...
So you can do it, but it's like driving at night without any lights. You're liable to crash, even if you think you know the road.
I just started to look at C, coming from a java background. I'm having a difficult time wrapping my head around pointers. In theory I feel like I get it but as soon as I try to use them or follow a program that's using them I get lost pretty quickly. I was trying to follow a string concat exercise but it wasnt working so I stripped it down to some basic pointer practice. It complies with a warning conflicting types for strcat function and when I run it, crashes completly.
Thanks for any help
#include <stdio.h>
#include <stdlib.h>
/* strcat: concatenate t to end of s; s must be big enough */
void strcat(char *string, char *attach);
int main(){
char one[10]="test";
char two[10]="co";
char *s;
char *t;
s=one;
t=two;
strcat(s,t);
}
void strcat(char *s, char *t) {
printf("%s",*s);
}
Your printf() should look like this:
printf("%s",s);
The asterisk is unnecessary. The %s format argument means that the argument should be a char*, which is what s is. Prefixing s with * does an extra invalid indirection.
You get the warning about conflicting types because strchr is a standard library routine, which should have this signature:
char * strcat ( char * destination, const char * source );
Yours has a different return type. You should probably rename yours to mystrchr or something else to avoid the conflict with the standard library (you may get linker errors if you use the same name).
Change
printf("%s",*s);
to
printf("%s",s);
The reason for this is printf is expecting a replacement for %s to be a pointer. It will dereference it internally to get the value.
Since you declared s as a char pointer (char *s), the type of s in your function will be just that, a pointer to a char. So you can just pass that pointer directly into printf.
In C, when you dereference a pointer, you get the value pointed to by the pointer. In this case, you get the first character pointed to by s. The correct usage should be:
printf( "%s", s );
BTW, strcat is a standard function that returns a pointer to a character array. Why make your own?
Replacing *s with s won't append strings yet, here is fully working code :
Pay attention to function urstrcat
#include <stdio.h>
#include <stdlib.h>
/* urstrcat: concatenate t to end of s; s must be big enough */
void urstrcat(char *string, char *attach);
int main(){
char one[10]="test";
char two[10]="co";
char *s;
char *t;
s=one;
t=two;
urstrcat(s,t);
return 0;
}
void urstrcat(char *s, char *t) {
printf("%s%s",s,t);
}
pointers are variable which points to address of a variable.
#include "stdio.h"
void main(){
int a,*b;
a=10;
b=&a;
printf("%d",b);
}
in the follwing code you will see a int 'a' and a pointer 'b'.
here b is taken as pointer of an integer and declared by giving'' before it.'' declare that 'b' is an pointer.then you will see "b=&a".this means b is taking address of integer "a" which is keeping value 10 in that particular memory and printf is printing that value.
all. I'm currently working with an old established code base for a new project which is basically undocumented (i.e. averages 1 one-line comment per file). I just ran into something which I haven't seen before and am not quite sure how to interpret.
Firstly, they define a function type and a function in the header file (.h) in the form:
typedef void (*SOME_FUNCTION)(void *data, EXECUTION_CONTEXT *ec);
void add_function(SOME_FUNCTION aFunction, void *data);
In the main source file (.c), there is a function defined:
void add_function(void (*f)(void *data), void *data)
{
(Some code here)
}
So okay, there's a function pointer... but what the heck happened to the second argument, ec? Why would someone use a code design like this? For reference, when the function add_function is used, it is used in this sort of form:
void passedFunction(void *data, EXECUTION_CONTEXT *ec)
{
(Stuff the function does.)
}
void CallingFunction()
{
data = (some data stuff);
add_function((SOME_FUNCTION)passedFunction, data);
}
So, as you can see, the passed functions use the correct form that fits the original SOME_FUNCTION argument signature, but the definition for the add_function arguments is short by one argument.
Formally, the results are undefined: you are only permitted to call a function via a function pointer if the types match.
As for what actually happens, it depends on the calling convention and what the function does with the arguments. Chances are, the results aren't going to be good.
To add on James' answer:
Since the default calling convention is most likely cdecl, the call site is responsible for cleaning up the stack after passedFunction returns. Since the call site knows that it passed just 1 argument to the callee, the compiler can clean up the stack normally (even though technically this is undefined behavior).
Change the calling convention on passedFunction to stdcall though, and you 're in for some fireworks.
From the example code below, it doesn't appear that the variable(s) that are defined in the function pointer matters during the check. The code below compiles without warning.
#include <stdio.h>
int temp(int (*m)());
int main(int argc, char *argv[]) {
return temp(main);
}
int temp(int (*m)()) {
return 1;
}
However, the code below throws an error.
#include <stdio.h>
int temp(void (*m)());
int main(int argc, char *argv[]) {
return temp(main);
}
int temp(void (*m)()) {
return 1;
}
Due to this; it seems that the compiler (at least in my case GCC) only cares what the return value of the function pointer will be. The interesting thing here is that you CAN send the parameters correctly but if you do NOT specify the parameter (in our example m()), then the variables in m() when called will be junk.