C using a pointer to a string in a function - c

a quick question. I'm trying to write a function which recieves a name of a string and prints its second character, But it won't compile (on http://ideone.com), can you address the issue? I don't see the problem as I am sending an address into the function, and asking to access the character in that address.
#include <stdio.h>
int main(void) {
char line[4] = "abc";
test(line);
return 0;
}
void test(int point) {
point++;
printf("%c",*point);
return;
}
The compile error that I am getting is -
Compilation error time: 0 memory: 10320 signal:0
prog.c: In function ‘main’:
prog.c:5:2: warning: implicit declaration of function ‘test’ [-Wimplicit-function-declaration]
test(line);
^~~~
prog.c: At top level:
prog.c:9:6: warning: conflicting types for ‘test’
void test(int point) {
^~~~
prog.c:5:2: note: previous implicit declaration of ‘test’ was here
test(line);
^~~~
prog.c: In function ‘test’:
prog.c:11:14: error: invalid type argument of unary ‘*’ (have ‘int’)
printf("%c",*point);
^~~~~~

Two problems here.
First, you use the function test before it's declared. So the function is implicitly declared as taking an unspecified number of arguments and returning int, i.e. int test(). This conflict with the definition void test(int point) that appears later.
The second issue is that you pass a char array (which decays to a char *) to test, but the function is expecting an int.
Move the definition of test to before main so that is defined before it's used, and change the point parameter from int to char *.
#include <stdio.h>
void test(char *point) {
point++;
printf("%c",*point);
return;
}
int main(void) {
char line[4] = "abc";
test(line);
return 0;
}

1) It wants a function prototype or for the function to be declared above your main.
2) The parameter point in
void test (int point)
is a pointer, not an int.

Related

Function Definition/Declaration Using Function Pointer `typedef` in C

UPDATE:
This was just something stupid. My PC crashed a few minutes after this, and after restart it throws the same error as to everyone else... Even when I go back to the original version using GIT. I guess something got messed up in the PCs RAM? XD
In C, can a function pointer type be used to declare and define a function?
I did this by mistake, but it worked as expected without throwing any warnings:
init.h:
typedef bool (*InitFunc)(void);
init.c:
#include <init.h>
#include <moduleX.h>
InitFunc initFuncs[N];
bool init(void)
{
...
initFuncs[n] = &moduleX_Init;
...
}
bool initTask(void* Args)
{
initFuncs[n]();
}
moduleX.h:
#include <init.h>
InitFunc moduleX_Init(void);
moduleX.c:
#include <moduleX.h>
InitFunc moduleX_Init(void)
{
...
return true;
}
As you can see, I defined the function moduleX_Init using the typedef of the function pointer. It compiled using GCC (arm-none-eabi-gcc) without even an warning and worked as expected.
I only did this by mistake, but when I noticed it, I was wondering if this is actually a compliant way to declare a function or it just happens to work with GCC.
EDIT:
If I do the declaration like this InitFunc moduleX_Init;, then I get the following error:
incompatible types when assigning to type InitFunc {aka _Bool
(*)(void)}' from type '_Bool'
So it seams, that when used in variable declarations, the function pointer types work as if they were a typedef of the return type. Is this standard behavior, or just the particularity of GCC?
No, you cannot use a function pointer typedef to declare or define a function. You can use use to use function pointer typedefs to specify the type of the return value and arguments.
You are declaring moduleX_Init to return a function pointer. Is that what you wanted? #SergeyA already gave you the warning for the assignment and here is the warning you get for moduleX_Init (gcc 8.3.0-6 without any arguments other the input file):
1.c: In function ‘moduleX_Init’:
1.c:6:9: warning: returning ‘int’ from a function with return type ‘InitFunc’ {aka ‘_Bool (*)(void)’} makes pointer from integer without a cast [-Wint-conversion]
return true;
^~~~
Your code is malformed, and there is no way it could have been compiled without warnings. Here is the one I am getting with your code:
<source>: In function 'init': <source>:11:18: warning: assignment to 'InitFunc' {aka '_Bool (*)(void)'} from incompatible pointer type '_Bool (* (*)(void))(void)' [-Wincompatible-pointer-types]
Your declaration
typedef bool (*InitFunc)(void);
InitFunc moduleX_Init(void);
declares a function which returns a pointer to function. By itself, there is nothing wrong with it, but when you try to use it like this:
initFuncs[n] = &moduleX_Init;
You are assigning function pointers with incompatible signatures, as initFuncs[n] has a type bool (*)(void).
In C, can a function pointer type be used to declare and define a function?
No. A function pointer is just a pointer. You can use it to call the function is points to, and for any case a pointer can be used
I did this by mistake, but it worked as expected without throwing any warnings
Well, as for the "any warnings" part compilers here disagree with you. For this line:
typedef bool (*InitFunc)(void);
clang 10 compiler says
dsp$ clang -c min.c
min.c:2:16: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
typedef bool (*InitFunc)(void);
^
min.c:2:9: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
typedef bool (*InitFunc)(void);
~~~~~~~ ^
min.c:2:14: error: function cannot return function type 'int (void)'
typedef bool (*InitFunc)(void);
^
2 warnings and 1 error generated.
And gcc 9.3 says
dsp$ gcc -c min.c
min.c:2:15: error: expected declaration specifiers or ‘...’ before ‘*’ token
2 | typedef bool (*InitFunc)(void);
| ^
As for the part "it worked as expected" what your expectations were?
Another similar typedef
typedef int(*Pfri)(int);
This is fairly common stuff and declares the name Pfri as a pointer to a function that returns an int and takes one int as argument, and this time the compilers will be happy with it.
C Example using this
#define N 10
#include <stdio.h>
typedef int(*Pfri)(int);
int plus3(int i) { return i*3; };
int plus4(int i) { return i*4; };
int main(void)
{
Pfri initFunc[N];
printf("fills array of function pointers\n");
for( int i = 0; i<N; i+=2 )
initFunc[i] = plus4, initFunc[1+i] = plus3;
printf("\
For odd indexes, function is \"int plus3(int i) { return i*3; };\"\n\
For even indexes, function is \"int plus4(int i) { return i*4; };\"\n\
Array has %d functions\n", N);
for( int i=0; i<N; i+=1 )
printf("f(%d)=%d\n", i,initFunc[i](i) );
return 0;
}
This program:
takes the above mentioned typedef and declares an array of them.
declares 2 functions compatible with this typedefed name
fills the array with pointers to the functions
calls each one and displays the results
Output
fills array of function pointers
For odd indexes, function is "int plus3(int i) { return i*3; };"
For even indexes, function is "int plus4(int i) { return i*4; };"
Array has 10 functions
f(0)=0
f(1)=3
f(2)=8
f(3)=9
f(4)=16
f(5)=15
f(6)=24
f(7)=21
f(8)=32
f(9)=27

Passing 2D array as pointer, gcc warning incompatible pointer type

I have the following versions of passing 2D array as pointer.
Version 1
#include <stdio.h>
void disp(int a[][5])
{
printf("a[0][3] = %d\n", a[0][3]); /* a[0][3] = 4 */
}
int main ()
{
int a[10] = {1,2,3,4,5,6,7,8,9,10};
disp(a);
return 0;
}
Version 2
#include <stdio.h>
typedef void(*callDisplay)(int*);
void disp(int a[][5])
{
printf("a[0][3] = %d\n", a[0][3]); /* a[0][3] = 4 */
}
int main ()
{
int a[10] = {1,2,3,4,5,6,7,8,9,10};
callDisplay fn = (callDisplay) &disp;
fn(a);
return 0;
}
Version 1 rises warning incompatible pointer type. expected int (*)[5] but argument is of type int * as expected. However, (Version 2) calling the same function with pointer is compiling without any such warnings.
gcc options: gcc -O0 -g3 -Wall -c -fmessage-length=0
Could somebody pass light on this?
If you remove the cast when assigning the function pointer you get:
tmp.c: In function ‘main’:
tmp.c:13:22: warning: initialization from incompatible pointer type [enabled by default]
callDisplay fn = &disp;
The cast is suppressing this warning even though by casting to a function pointer of a different type you have invoked undefined behavior when you call the function pointer. Basically, you should never need to cast a function pointer as it will hide any warnings like this.
If you fix the function pointer you get the following code:
typedef void(*callDisplay)(int[][5]);
void disp(int a[][5])
{
printf("a[0][3] = %d\n", a[0][3]); /* a[0][3] = 4 */
}
int main ()
{
int a[10] = {1,2,3,4,5,6,7,8,9,10};
callDisplay fn = &disp;
fn(a);
return 0;
}
Which when you compile you get the same warning as your first example:
tmp.c: In function ‘main’:
tmp.c:14:5: warning: passing argument 1 of ‘fn’ from incompatible pointer type [enabled by default]
fn(a);
^
tmp.c:14:5: note: expected ‘int (*)[5]’ but argument is of type ‘int *’
This function declaration
typedef void(*callDisplay)(int*);
has compatible argument when is called like
fn(a);
The problem is related to this casting
callDisplay fn = (callDisplay) &disp;
it is wrong.
That is the program has undefined behaviour.
According to the C Standard (6.3.2.3 Pointers)
8 A pointer to a function of one type may be converted to a pointer to
a function of another type and back again; the result shall compare
equal to the original pointer. If a converted pointer is used to
call a function whose type is not compatible with the referenced type,
the behavior is undefined.

Call a c function with a const matrix argument using a const cast

I am trying to call a c function with a const matrix argument using a const cast, but can't find the syntax that stops the gcc compiler complaining. The code below compiles without complaining if all "const " casts are removed. The quesion is similar to C function const multidimensional-array argument strange warning but no fully satisfactory solution was offered there. In the following code, if the first call to g() works, then the second call to g() should also work, since it is syntactically identical. But it does not. The second version of g() is preferred, because it does not require knowing in advance the type of the matrix.
/* file t.c */
void f(const int a[2]) {/*empty*/}
void g(const int b[2][2]) {/*empty*/}
int main()
{
int a[2];
int b[2][2];
f((const int (*)) a); /* ok */
f((const typeof(&a[0])) a); /* ok */
g((const int (*)[2]) b); /* ok */
g((const typeof(&b[0])) b); /* compiler complains */
}
$ gcc -o t t.c
t.c: In function ‘main’:
t.c:13:2: warning: passing argument 1 of ‘g’ from incompatible pointer type [enabled by default]
g((const typeof(&b[0])) b); /* compiler complains */
^
t.c:3:10: note: expected ‘const int (*)[2]’ but argument is of type ‘int (*)[2]’
void g(const int b[2][2]) {/*empty*/}
Yes, this lack of possibility to call a function with const 2D arrays with a non-const argument is really a defect in the C specification.
To move around it remember that
void g(const int b[2][2]) {/*empty*/}
is rewritten as
void g(const int (*b)[2]) {/*empty*/}
so this shows you how you'd have to convert, to a const int (*)[2], that is a pointer to an array of 2 double.
g( (const int (*)[2])b );
The const in the declaration header means that the function cannot change the contents of the argument. It is an information to the caller(compiler) and programmer. So there is no reason to make a const typecast then calling the function. It is totally superfluous.

conflicting type for funct in C

I am trying to run the code below and i am getting the error messages below.
Program:
int main()
{
int (*res)[3],i;
res=func();
}
int (*func())[3]
{
static int arr[3][3]={1,2,3,4,5,6,7,8,9};
return arr;
}
Error:
PointerTo1D.c: In function ‘main’:
PointerTo1D.c:6:5: warning: assignment makes pointer from integer without a cast [enabled by default]
res=func();
^
PointerTo1D.c: At top level:
PointerTo1D.c:11:7: error: conflicting types for ‘func’
int (*func())[3]
^
PointerTo1D.c:6:6: note: previous implicit declaration of ‘func’ was here
res=func();
Could someone please help me out here???
res is a pointer to an array with 3 elements of int
int (*func())[3]: func is a function which returns a pointer to array with 3 elements of int
Because there is no prototype for function func() you got:
warning: implicit declaration of function 'func'
res=func();
which means that compiler use default prototype int func().
There is next warning:
warning: assignment makes pointer from integer without a cast [enabled by default]
res=func();
because default prototype is used, compiler assumes that function func() returns int which is than assigned as a pointer to res which is the pointer
When code for function func() is reached you get error:
error: conflicting types for 'func'
int (*func())[3]
Solution is to provide proper prototype before main.
int (*func())[3];
int main()
{
...
}
Update: There is also warning:
warning: missing braces around initializer [-Wmissing-braces]
static int arr[3][3]={1,2,3,4,5,6,7,8,9};
It is better to use:
static int arr[3][3]={{1,2,3}, {4,5,6}, {7,8,9}};
You have to change your code to
int** func() //change here
{
static int arr[3][3]={1,2,3,4,5,6,7,8,9};
return arr;
}
and
int** func(); //forward declaration
int main()
{
int ** res = NULL,i = 0; //change here
res=func();
return 0;
}
Any function you call from your main() should either be defined before main() or atleast have a forward declaration before main() so that the comipler has a way to know the function signature before the function is used (called).
Note: Usually, it's not a good practice to use static for this purpose. Dynamic memory allocation (malloc()/calloc()) is designed exactly for this purpose.
First if you want to return a pointer do like this :
(int **)func() {
...
return arr;
}
Then define res like this :
int ** res;
res = func();
If a function is called without a declaration being visible, it is assumed to be old-style declared, with external linkage, and returning an int in C89:
extern int func();
The empty parentheses (an old-style declaration) mean: No argument checking required, function takes fixed number of default-promoted arguments.
In C99, implicit declarations have been removed, Gcc warns about them by default, but sticks to the old behaviour, probably for backward compatibility. They can be turned into errors for example with gcc -std=c99 -pedantic-errors, or gcc -std=gnu89 -Werror=implicit-function-declaration if you want to stick to GNU89 (what I suspect was specified from the warnings given).
To fix the problem, the function needs at least to be declared before use:
int (*func())[3];
int main() {
func();
}
This still uses old-style declarations, marked obsolescent in all C standards, I'd suggest using prototypes to ensure argument checking:
int (*func(void))[3];
int main(void) { /* ... */ }

C Function returning an Array

I always thought that when you want to return an array from a function, the only way to do that was using pointers like so:
char * func();
But yesterday, while I was going through K & R, I noticed wrongly assumed that char x()[] is also a valid construct. So I went ahead to test this out and wrote up the following code:
#include <stdio.h>
#include <stdlib.h>
char string1[10] = "123456789";
char x(void)[10];
int main(void) {
printf("string returned by x() is %s",x());
return EXIT_SUCCESS;
}
char x(void)[10] {
return x;
}
Compiling using GCC on Windows, this threw the following errors:
..\src\07arrreturn.c:7:6: error: 'x' declared as function returning an array
..\src\07arrreturn.c: In function 'main':
..\src\07arrreturn.c:10:2: warning: format '%s' expects argument of type 'char *', but argument 2 has type 'int' [-Wformat]
..\src\07arrreturn.c: At top level:
..\src\07arrreturn.c:14:6: error: 'x' declared as function returning an array
..\src\07arrreturn.c: In function 'x':
..\src\07arrreturn.c:15:2: warning: return makes integer from pointer without a cast [enabled by default]
What is happening? am I mis-understanding what the book says? How can you return more than one value (or address) from a function? Isn't that restricted by the fact that you only have a single limited size CPU register that can hold the return value? If you have to return a big chunk of data, you can do so only by returning the address to it right?
Whats the deal with char x()[]? Is such a thing even used?
EDIT: I DID in fact misread the stuff from K&R. See comment below.
char x()[] is also a valid construct
Not as-is, and not quite in this context.
You can use similar syntax to:
declare a pointer to array: char (*arrPtr)[20];
declare an array of function pointers: void (*foo[20])(void);
dereference the return value (pointer) of a function call: char *foo(); char c = foo()[0];
declare a function that returns a pointer to array: char (*foo())[20]
or the same thing with a function pointer: char (*(*foo)())[20]
Which one of these are you looking for?
The C standard (ISO/IEC 9899:2011) says unequivocally:
6.7.6.3 Function declarators (including prototypes)
Constraints
1 A function declarator shall not specify a return type that is a function type or an array
type.
Thus your code is invalid.
K&R C is quite old. In ANSI C (C89), functions returning arrays aren't allowed and what you see is the result of this. First, you get errors for the declaration of x() as a function returning an array and due to this error, x() is never correctly declared and thereby treated like a function returning an int (because this used to be the default return type). This returned int is then supposed to be interpreted as char * generating the final warning.
If you need to return an array, you can wrap it in a struct. Otherwise return a pointer (make sure that the memory it points to is valid after returning).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char string1[10] = "123456789";
struct ret_s {
char string1[10];
};
struct ret_s x(void);
int main(void) {
struct ret_s r = x();
printf("string returned by x() is %s\n", r.string1);
return EXIT_SUCCESS;
}
struct ret_s x(void) {
struct ret_s r;
strcpy(r.string1, string1);
return r;
}

Resources