Method signature in C, passing pointer on static array - c

I have the following arrays:
char* mask[9];
int hSobelMask[9] = {
-1, -2, -1,
0, 0, 0,
1, 2, 1};
I want to give a pointer on this array to a method like this:
int H = applyMask(&mask, &hSobelMask);
The signature of the applyMask function is the folowing:
int applyMask(char** mask[9], int* sobelMask[9]);
But I get the following compile warning:
demo.c: In function ‘customSobel’:
demo.c:232:7: warning: passing argument 1 of ‘applyMask’ from incompatible pointer type
demo.c:181:5: note: expected ‘char ***’ but argument is of type ‘char * (*)[9]’
demo.c:232:7: warning: passing argument 2 of ‘applyMask’ from incompatible pointer type
demo.c:181:5: note: expected ‘int **’ but argument is of type ‘int (*)[9]’
What does this warning mean, how do I get rid of it ?

You want to pass the pointers to these arrays? So you're probably looking for this:
int applyMask(char* (*mask)[9], int (*sobelMask)[9]);

int applyMask(char** mask, int* sobelMask);

A char * ___[9] is an array of char *, and a char * * ___[9] is an array of char * *. They're not compatible. Just change your function signature to this:
int applyMask(char** mask, int* sobelMask)
or this:
int applyMask(char* mask[], int sobelMask[])
Edited to add (after Shahbaz's comment below): Call your function like this:
int H = applyMask(mask, hSobelMask);
There's no need for those &s, since an array variable already is a pointer to the contents of the array.

Related

correct return type for C function?

I am using an array of strings inside my function declared like this
char (*array)[PATH_MAX] = malloc (1000 * sizeof *array);
Allocating 1000 char pointers of size PATH_MAX (1024).
I want the function to return that specific data structure, i.e. return the pointer array. But I can't manage to choose the correct return type.
warning: returning 'char (*)[1024]' from a function with return type 'int' makes integer from pointer without a cast [-Wint-conversion]
I get that I can't have int as return type, but char** doesn't work either.
warning: returning 'char (*)[1024]' from a function with incompatible return type 'char **' [-Wincompatible-pointer-types]
I've tried using char (*)[1024] as return type, but it gives me generic C error messages, leading me to believe that I am not using the correct syntax.
error: expected identifier or '(' before ')' token
38 | char (*)[1024] read_dir (char *path) {
| ^
Is there a correct syntax for achieving this or am I just doing it wrong?
You need to define the function as follows:
char (*read_dir(char *path))[PATH_MAX] {
This specifies the return type as a pointer to an array of size PATH_MAX of char *.
Time for typedef
typedef char arr1k_char[1000];
arr1k_char *foo(int n) {
arr1k_char *x = malloc(n * sizeof *x);
return x;
}
https://ideone.com/Cqxa61

Cast from (void**) to (int*) and viceversa

I did a function f which takes as input a (void*), convert it to a (int*) and print the value.
#include <stdlib.h>
#include <stdio.h>
void f(void* p)
{
int *pi = (int*)p;
printf("%d\n", *pi);
}
int main()
{
int x = 1;
int *px = &x;
void *pv = (void*)px;
f(pv);
return 0;
}
Is it possible to implement a function:
void f2(void** pp);
such that it performs the "same" operations of the function f? My goal is to learn how to convert a (int*) to a (void**) and viceversa.
EDIT: error and warning of #tadman code (I did a mistake)
fvv.c: In function ‘f2’:
fvv.c:10:12: warning: initialization of ‘int *’ from incompatible pointer type ‘int **’ [-Wincompatible-pointer-types]
10 | int *pi = (int**)p;
| ^
fvv.c:12:17: error: invalid type argument of unary ‘*’ (have ‘int’)
12 | printf("%d\n", **pi);
|
EDIT2
fvv.c: In function ‘main’:
fvv.c:19:5: warning: passing argument 1 of ‘f2’ from incompatible pointer type [-Wincompatible-pointer-types]
19 | f2(&px);
| ^~~
| |
| int **
fvv.c:7:16: note: expected ‘void **’ but argument is of type ‘int **’
7 | void f2(void** p)
You can take any level of indirection you want, up to the blatantly, utterly absurd (void*******), but I'm not sure why this would be useful:
void f2(void** p)
{
// Note you must maintain the same level of indirection
int **pi = (int**)p;
// Since this is a ** pointer, it requires ** to fully de-reference
printf("%d\n", **pi);
}
To call this you need a pointer to a pointer:
int x = 1;
int *px = &x;
f2((void**) &px);
In C terms a pointer to a pointer is often interpreted to mean one of the two following things:
A two dimensional array
A mutable pointer argument
Neither of those apply here.
That being said, in C there's not a lot of rules as to what you can and can't convert. If you want to do it, C isn't going to get in your way, even if the resulting code makes no sense or will crash immediately when executed.
You can convert int* to void** and back again, C won't care, but you should have a really good reason for doing such a thing. Normally arbitrary pointers are almost always specified as void*, and as this can be recast into whatever you want, it's sufficient.
For example, you can specify void* as an argument when that pointer is actually int**, something you'll see quite often, as in thread_create taking a void* arg argument. That's not limited to mere pointers, you can cast to your heart's content.

Warning: passing argument 2 of 'transform_labels' from incompatible pointer type [-Wincompatible-pointer-types]|

My compiler gives me this warning: passing argument 2 of 'transform_labels' from incompatible pointer type [-Wincompatible-pointer-types] with this note: expected 'int (*)[10]' but argument is of type 'int **'
My code:
void transform_labels(int array[60000], int labels[60000][10], int NPAT){
for(int i = 0; i < NPAT; i++){
int aux = array[i];
labels[i][aux] = 1;
printf("%d\n ",*labels[i]);
if ((i+1) % 10 == 0) putchar('>');
}
}
int main() {
load_mnist();
int loop;
int** labels;
allocate_mem(&labels, 60000, 10);
printf("HERE");
transform_labels(train_label, labels, 60000);
return 0;
}
A pointer to a pointer cannot be converted to a pointer to an array. While an array can be converted to a pointer that only applies to the outermost dimension of a multidimensional array.
You need to change the declaration of your function:
void transform_labels(int *array, int **labels, int NPAT){
You are allowed to pass a pointer instead of the first dimension of a function argument, and vice-versa, but all other dimensions must match. You have a second dimension [10].
You can pass it a pointer to an array of size 10, but that might just push your problem up to another point in the code, such as your allocate function. The following should compile, but it is not clear that this is what you want:
typedef int LabelSub[10];
LabelSub* labels;
allocate_mem(&labels, 60000, 10);

expected ‘const char *’ but argument is of type ‘char **’ in C

I am trying to write a function which searches the array looking for the specified key.The argument n specifies the effective size of the array,which must be sorted according to the lexicographic order imposed by strcmp.If the key if found,the function returns the index in the array at which that key appears.So ,it can return the index of the substring.However,it come two errors which I can't fix with.Please help.
jiebin#jiebin-ThinkPad-Edge-E530:~/Program_C/programming_abstractions_in_c/FindStringInSortedArray$ gcc FindStringInSortedArray.c -o FindStringInSortedArray
FindStringInSortedArray.c: In function ‘FindStringInSortedArray’:
FindStringInSortedArray.c:7:3: warning: passing argument 1 of ‘strlen’ from incompatible pointer type [enabled by default]
/usr/include/string.h:399:15: note: expected ‘const char *’ but argument is of type ‘char **’
jiebin#jiebin-ThinkPad-Edge-E530:~/Program_C/programming_abstractions_in_c/FindStringInSortedArray$
This is my code:
#include<stdio.h>
#include<string.h>
int FindStringInSortedArray(char *key,char *array[],int n)
{
int mid,cmp;
int low=strlen(array)-n;
int high=n;
if(low > high) return(-1);
mid = (low+high)/2;
cmp = strcmp(key,array[mid]);
if(cmp==0) return(mid);
if(cmp<0){
return(FindStringInSortedArray(key,array,n/2));
}else{
return(FindStringInSortedArray(key,array+n/2,n));
}
}
int main()
{
char key[2]="ab";
char *array[10]={"ab","bc","cd","de","ef","fg","gh","hi","ij","jk"};
int test=FindStringInSortedArray(key,array,10);
printf("Result:%d\n",test);
return 0;
}
int low=strlen(array)-n; is wrong. Pass the array size as different parameter like:
int FindStringInSortedArray(char *key,char *array[],int n, int arraysize)
Since arrays decay into pointers in functions. Declaration of strlen is of the form
strlen (const char*)
And you are passing *array[] whose type decays to char * *.
In C99 there are three fundamental cases where array name doesn't decay into pointers to first elements:
when it's the argument of the & (address-of) operator.
when it's the argument of the sizeof operator.
When it's a string literal of type char [N + 1] or a wide string literal of type wchar_t [N + 1] (N is the length of the string) which is used to initialize an array, as in char str[] = "foo"; or wchar_t wstr[] = L"foo";.
In C11, the newly introduced alignof operator doesn't let its array argument decay into a pointer either.
When you call strlen, it is expecting a char* (i.e. a string) as an argument, but you provide it with array which is a char** (i.e. an array of strings).
What you want is the size of the array, i guess. There is no way to know it, in C. The only way is to pass the size of the array as an argument :
int FindStringInSortedArray(char *key,char *array[],int n, int len)

Pass a char pointer array to a function in C?

I have the following code:
int main(){
char **array;
char a[5];
int n = 5;
array = malloc(n *sizeof *array);
/*Some code to assign array values*/
test(a, array);
return 0;
}
int test(char s1, char **s2){
if(strcmp(s1, s2[0]) != 0)
return 1;
return 0;
}
I'm trying to pass char and char pointer array to a function, but the above code results in the following errors and warnings:
temp.c: In function ‘main’:
temp.c:6:5: warning: implicit declaration of function ‘malloc’ [-Wimplicit-function-declaration]
temp.c:6:13: warning: incompatible implicit declaration of built-in function ‘malloc’ [enabled by default]
temp.c:10:5: warning: implicit declaration of function ‘test’ [-Wimplicit-function-declaration]
temp.c: At top level:
temp.c:15:5: error: conflicting types for ‘test’
temp.c:15:1: note: an argument type that has a default promotion can’t match an empty parameter name list declaration
temp.c:10:5: note: previous implicit declaration of ‘test’ was here
temp.c: In function ‘test’:
temp.c:16:5: warning: implicit declaration of function ‘strcmp’ [-Wimplicit-function-declaration]
I'm trying to understand what the problem is.
First of all, you should include the necessary header files. For strcmp you need <string.h>, for malloc <malloc.h>. Also you need to at least declare test before main. If you do this you'll notice the following error:
temp.c: In function ‘test’:
temp.c:20:5: warning: passing argument 1 of ‘strcmp’ makes pointer from integer without a cast [enabled by default]
/usr/include/string.h:143:12: note: expected ‘const char *’ but argument is of type ‘char’
This indicates that test() should have a char * as first argument. All in all your code should look like this:
#include <string.h> /* for strcmp */
#include <malloc.h> /* for malloc */
int test(char*,char**); /* added declaration */
int main(){
char **array;
char a[5];
int n = 5;
array = malloc(sizeof(*array));
array[0] = malloc(n * sizeof(**array));
/*Some code to assign array values*/
test(a, array);
free(*array); /* free the not longer needed memory */
free(array);
return 0;
}
int test(char * s1, char **s2){ /* changed to char* */
if(strcmp(s1, s2[0]) != 0) /* have a look at the comment after the code */
return 1;
return 0;
}
Edit
Please notice that strcmp works with null-terminated byte strings. If neither s1 nor s2 contain a null byte the call in test will result in a segmentation fault:
[1] 14940 segmentation fault (core dumped) ./a.out
Either make sure that both contain a null byte '\0', or use strncmp and change the signature of test:
int test(char * s1, char **s2, unsigned count){
if(strncmp(s1, s2[0], count) != 0)
return 1;
return 0;
}
/* don' forget to change the declaration to
int test(char*,char**,unsigned)
and call it with test(a,array,min(sizeof(a),n))
*/
Also your allocation of memory is wrong. array is a char**. You allocate memory for *array which is itself a char*. You never allocate memory for this specific pointer, you're missing array[0] = malloc(n*sizeof(**array)):
array = malloc(sizeof(*array));
*array = malloc(n * sizeof(**array));
Error 1
temp.c:6:13: warning: incompatible implicit declaration of
built-in function ‘malloc’ [enabled by default]
Did you mean this?
array = malloc(n * sizeof(*array));
Error 2
temp.c:15:5: error: conflicting types for ‘test’
temp.c:15:1: note: an argument type that has a default promotion can’t
match an empty parameter name list declaration
temp.c:10:5: note: previous implicit declaration of ‘test’ was here
You are passing the address of the first element of an array a:
test(a, array);
So the function signature should be:
int test(char* s1, char** s2)
You have several problems. The first is that the prototype is wrong. The data type for a decays to a char pointer when passing to a function, so you need:
int test (char* s1, char** s2) { ... }
However, even when you fix this, the test declaration isn't in scope when you first use it. You should either provide a prototype:
int test (char* s1, char** s2);
before main, or simply move the whole definition (function) to before main.
In addition, don't forget to #include the string.h and stdlib.h headers so that the prototypes for strcmp and malloc are available as well.
When you pass an array of char to your function, the argument decays to a pointer. Change your function arguments to
int test(char* s1, char **s2);
^
^
and your code should at least compile

Resources