I understand why this does not work:
int main(int argc, char *argv[]) {
char *names[] = {"name1", "name2", "name3", "name4"};
int i = 0;
while (i++ <= 3) {
printf("%s\n", *names++);
}
}
Error:
a.c: In function 'main':
a.c:16: error: wrong type argument to increment
shell returned 1
It's because I am trying to increment an array variable (and NOT a pointer). Please don't mind the line number in the error message, I have lot's of commented code above and below what I have put up here.
However, I do not understand why this piece of code works:
void myfunc(char *names[]) {
int i = 0;
while (i++ <= 3) {
printf("%s\n", *names++);
}
}
int main(int argc, char *argv[]) {
char *names[] = {"name1", "name2", "name3", "name4"};
myfunc(names);
}
How can we increment names in myfunc()? It's still a local array variable in myfunc().
Could someone please help?
Thanks.
In the 1st example names is an array. Arrays cannot be incremented.
In the 2nd example names is a pointer. Pointers can be incremented.
Background to why the 2nd example compiles:
A [] in a variable definition in a function declaration is the same as (another) *.
So this
void myfunc(char * names[]);
is equivalent to
void myfunc(char ** names);
The latter makes it obvious that here names is not an array but a pointer.
When you pass an array as a function argument, it turns it into a pointer to the first element in the array. This means that when you declare an array and attempt to increment it directly, you are trying to increment an array. When you pass the array as an argument, on the other hand, it is passed as a pointer, so you can increment it.
If you wish to pass the array as an array, and not as a pointer, you might consider using std::array, which is a fixed size container.
EDIT: I apologise. std::array is only available in C++.
When you pass array to a function it decays into pointer.
Refer here to know about array-decaying
Related
In my code I need to pass a pointer to an array of pointers as a function argument. Code snippets:
struct foo * foos[] = {NULL, NULL, NULL};
some_function(&foos);
and:
static void some_function(struct foo ** foos) {
foos[0] = get_a_foo();
/* some more code here */
}
This works as expected (after some_function() returns, foos[] contains the pointers I set there), but I get a compiler warning for the call to some_function():
note: expected ‘struct foo **’ but argument is of type ‘struct foo * (*)[3]’
What’s the correct way to accomplish what I want (i.e. pass a pointer to the array of pointers to the function, so that the function can change pointers in the array)?
Pass it as some_function(foos)
struct foo ** is a pointer to a (single) pointer to a struct foo, not a pointer to an array of pointers, hence the compiler warning.
An easy way to silence the compiler warning is to call the function as follows:
some_function(&foos[0]);
This will pass a pointer to the first member, i.e. a struct foo **, rather than to the whole array; the address is the same in both cases.
If I understand what you are trying to do (fill your array of pointers with a call to a function), then your understanding of how to accomplish that is a bit unclear. You declare foos, which itself is an array. (an array of what? pointers).
You can treat it just like you would treat an array of char (from the standpoint that you can simply pass the array itself as a parameter to a function and operate on the array within a function) You can do that and have the changes visible in the caller because despite the array address itself being a copy in the function, the values it holds (the individual pointer address) remains the same.
For example:
#include <stdio.h>
char *labels[] = { "my", "dog", "has", "fleas" };
void fillfoos (char **f, int n)
{
int i;
for (i = 0; i < n; i++)
f[i] = labels[i];
}
int main (void) {
char *foos[] = { NULL, NULL, NULL };
int i, n = sizeof foos / sizeof *foos;
fillfoos (foos, n);
for (i = 0; i < n; i++)
printf ("foos[%d] : %s\n", i, foos[i]);
return 0;
}
Above foos is simply treated as an array passed to the function fillfoos which then loops over each pointer within foos filling it with the address to the corresponding string-literal contained in labels. The contents of foos is then available back in main, e.g.
Example Use/Output
$ ./bin/fillptp
foos[0] : my
foos[1] : dog
foos[2] : has
If I misunderstood your question, please let me know and I'm happy to help further.
You need a pointer to an array as clearly mentioned in the warning.
Below is a minimal code sample that explains the same.
#include<stdio.h>
typedef struct foo{
}FOO;
static void some_function(FOO* (*foos)[]) {
// foos above is a pointer to an array of pointers.
// Refer the link to start with a simple example.
// Access it like foos[0][0] which is the same as (*foos)[0]
/* some more code here */
}
int main(int argc, char **argv) {
FOO* foos[]={0,0,0}; // Here you have an array of pointers
some_function(&foos);
}
The program crashes right in the instruction mentioned in the source code (I didn't write all the code because it's too long)
int main()
{
char screen[24][80];
//......every thing is well until this instruction
backgrounds(5,screen);
//......the program doesn't execute the rest of the code
}
//______________________________________________________
//this is a header file
void backgrounds(int choice,char **screen)
{
if(choice==5)
{
screen[18][18]='-';
screen[18][19]='-';
screen[18][20]='-';
}
}
A char [24][80] cannot be converted to a char **.
When passed to a function, an array decays into a pointer to its first element. This is simple for a 1 dimensional array, but less so for higher dimensions.
In this case, a char [24][80] is an array of char [80]. So passing a variable of this type to a function yields a char (*)[80].
Change your function definition to either this:
void backgrounds(int choice,char (*screen)[80])
Or this:
void backgrounds(int choice,char screen[24][80])
Or you can use a variable length array for maximum flexibility:
void backgrounds(int choice, int x, int y, char screen[x][y])
I'm trying to have a function set a global variable to the value that i pass it. I know how to do this with something like an int, but i can't seem to get it to work with a string array. Here is the code:
#include "stdio.h"
char *(*(*foo));
void setFunc(char *arr[]);
int main(int argc, char const *argv[]) {
char *bar[] = {"Test", "Test 2"};
setFunc(bar);
printf("%s %s\n", *foo[0], *foo[1]);
return 0;
}
void setFunc(char *arr[])
{
foo = &arr;
}
This outputs: "Test (null)" And is as close as i could get.
I hope i am not missing something stupid. I am pretty new to C and pointers are still pretty confusing.
You do not need the third * on your global definition of foo. You should change it to char** foo;
char* bar[] is defining a pointer to an array of chars.
Assigning foo = arr (instead of foo = &arr) will assign the address of the pointer foo to be the same location as arr.
You can then change your print line to:
printf("%s %s\n", foo[0], foo[1]);
I think the difficulties come with
char ***foo;
and how that may lead to ambiguity with the variable
*foo[0]
. The computer does not know whether you mean:
(*foo)[0]
or:
*(foo[0])
. These calls to the foo variable will yield different results. You want:
(*foo)[0]
which dereferences foo to the array of char*'s, and then takes the first element of that array, and prints it.
I suggest taking out one of the pointers to make
char **foo;
This will make it easier to use, as you can just say:
foo[0]
without any ambiguity.
This is the question i am working on.
"A simple encryption scheme named "rotate13" for encrypting text is to convert each letter (a…z or A...Z) to another letter by counting forward 13 letters, looping around from 'z' to 'a' or 'Z' back to 'A' if necessary.
Write a function named rotate13 which takes a single null-terminated string as a parameter
and converts it to its rotate13 equivalent. The function should modify the string directly, and it
should not return anything. Remember, only letters should change; all other characters remain
the same. You may assume that ctype.h is correctly included at the top of your program so
that you can use any functions within the library if you wish. "
And this is the error i keep getting
"error C2664: 'rotate13' : cannot convert parameter 1 from 'char (*)[10]' to 'char *[]'"
Thanks for the help. It will help me in my revisions for finals.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int rotate13(char *array[]);
int size=10;
int main()
{
char arr[10];
printf("Please enter the letters you wish to encrypt: ");
scanf("%s",&arr);
printf("%s",arr);
rotate13(&arr);
system ("pause");
return 0;
}
int rotate13(char *array[])
{
int pointer;
while(*array[pointer]!='\0')
{
if(isupper(*array[pointer])!=0)
{
if(*array[pointer]<'N')
*array[pointer]=*array[pointer]+13;
else
*array[pointer]=*array[pointer]-13;
}
else
{
if(*array[pointer]<'n')
*array[pointer]=*array[pointer]+13;
else
*array[pointer]=*array[pointer]-13;
}
pointer++;
}
printf("%s", *array);
return 0;
}
Remove & from scanf("%s",&arr);
scanf("%s",arr);
rotate13 is expecting an argument of type char ** but, by passing &arr you are passing it an argument of type int (*)[10]. Passing arr to rotate13 will solve your problem.
rotate13(arr);
You want to pass a string as the parameter of rotate13, so use either
int rotate13(char *array);
or
int rotate13(char array[]);
and pass arr like rotate13(arr). the same for scanf("%s",arr);
And inside the function rotate13, pointer is an int(bad variable name) that isn't initialized. To access the characters, use array[pointer], not *arr[pointer].
The function should look like this:
int rotate13(char array[])
{
int n;
while(array[n]!='\0')
{
Use rotate13(arr); instead of rotate13(&arr); and parameter should be char [] instead of char *[]
rotate13(&arr); sends the address of the array to the function which causes the parameter mismatch
As other answers have said, you're better of with int rotate13(char array[]). To understand the context, you should read this wonderful page: http://c-faq.com/aryptr/
Basically, passing a pointer to an array is redundant here, because in C when you pass an array to a function, what's actually passed is a pointer to its first element. Arrays are inherently passed by reference.
Some things need to be explained. "string" in C is the address of a character buffer.
Since the identifier arr in char arr[10]; degrades to a pointer to the first element of the array, So you don't need to specify a pointer (i.e &) to the string in the argument to scanf.
By passing &arr in your scanf as scanf("%s",&arr); the pointer passed to scanf is now a doubly-indirect pointer (it is a pointer to a pointer to the beginning of the buffer) and will likely cause the program to crash or other bad behaviour.
The strings in c, dont require &array as they implicitly pass address of the first element of the character array
So your two statments scanf("%s",&arr) should be simply scanf("%s",arr) and rotate13(&arr) should be rotate13(arr). notice that address of the first element are implicitly passed in the function calls.
Your function rotate13(char *array[ ]) is completely wrong way of doing it
char arr[10] -> can hold single string ( simply an array )
char *array[] -> can hold multiple strings ( also called array of pointers)
the formal parameter should be rotate13(char array[]) or rotate13(char *array).
After seeing your code I believe your not changing the contents of arr so you require a call by value instead of a call by address
char array[] - > call by value , char *array -> call by address
Your variable int pointer is not initialized before its use, Its dangerous. First initialize is to zero.
Change all the occurences of *array[pointer] to array[pointer]
If your wishing to change the contents of arr use call by address just change rotate13(char array[]) to rotate13(char *array) and Dont forget to initialize pointer variable to zero .
Please let me know how can I pass a pointer to the array of structures in C as a function argument.
Below is my code.
#include <stdio.h>
#include<strings.h>
typedef struct _Alert
{
char MerchantNo[21];
time_t last_update;
} Alert;
typedef Alert *PALERT;
int set(PALERT palertMerch[5], int *merchnoIndex, char * txnMerchant)
{
strcpy(palertMerch[*merchnoIndex]->MerchantNo, txnMerchant);
*(merchnoIndex) = *(merchnoIndex) + 1 ;
return 0;
}
int main()
{
Alert alert[5];
for(int i =0; i<5;i++)
{
memset(alert[i].MerchantNo, 0x00, 21);
alert[i].last_update = (time_t)0;
}
char *p = "SACHIN";
int index = 0;
set(alert[5], index, p);
}
Error message
"3.c", line 34: argument #1 is incompatible with prototype:
prototype: pointer to pointer to struct _Alert {array[21] of char MerchantNo, long last_update} : "3.c", line 14
argument : struct _Alert {array[21] of char MerchantNo, long last_update}
"3.c", line 34: warning: improper pointer/integer combination: arg #2
cc: acomp failed for 3.c
You just pass the array, it'll get decayed to the pointer to the first array element:
set( alert, &index, p );
Note that I also corrected your second error of passing integer as a pointer for the second argument.
Edit 0:
I missed the declaration of PALERT - your function definition is wrong, it should be something like:
int set( PALERT palertMerch, int* merchnoIndex, const char* txnMerchant )
{
assert( *merchnoIndex >= 0 && *merchnoIndex < 5 );
strcpy( palertMerch[*merchnoIndex].MerchantNo, txnMerchant );
...
}
I know, arrays and pointers are a bit confusing in C, and you were trying to jump to arrays of pointers already :)
You actually cannot pass an array to a function. What happens when you do, is that a pointer to the first element in an array is passed in instead. (That proccess is often described as "an array decays into a pointer").
That is,
set(alert, index, p);
Is just the same as:
set(&alert[0], index, p);
(Note that you called it as set(alert[5], index, p); , this just passes in the 6. element of your array , which btw is invalid, as your array only have room for 5 elements.)
So, what you do when you want to pass an array to a function is you
Pass a pointer to the first element in the array (which can be done by just writing name_of_array or &name_of_array[0]
Add another argument that is the length of the array. You might need this as if your array can have different sizes, and you cannot know how many elements an array have, if all you got is a pointer to its first element:
Let's skip item 2. above for now, you can just do:
//PALERT is already a pointer, otherwise specify the first argument as:
//ALERT *palertMerch
int set(PALERT palertMerch, int *merchnoIndex, char * txnMerchant)
{
strcpy(palertMerch[*merchnoIndex]->MerchantNo, txnMerchant);
*(merchnoIndex) = *(merchnoIndex) + 1 ;
return 0;
}
And call it like:
char *p = "SACHIN";
int index = 0;
set(alert, index, p);
btw, unless you have a good reason, try not to hide a pointer in a typedef as you do in typedef Alert *PALERT; doing so often gets confusing.
remove the array brackets and it should work.
The reason for this is that array notation is an easier way to represent sequences of items in memory. For example, in an array a[5], you can access the third element as a[3] or *(a+3).
Your function takes type PALERT *[5]. You are passing in Alert[5] instead. There are other problems with your code that need fixing before it will successfully run.