I've been trying to write tideman.c for CS50 ps3. I'm running merge sort, and there is a struct array where each element is composed of two ints. I'm trying to pass that array into a function, but I keep getting the error message: error: declaration shadows a variable in the global scope.
This is my function declaration:
void Merge_Sort(pair pairs[], int l, int r)
and this is my call:
int r = pair_count - 1;
int l = 0;
Merge_Sort(pairs, l, r);
return;
pair_count is an int, pairs is the aforementioned array of type pair (two ints). Any help would be really appreciated! The compiler points to an error with the declaration itself. It says that the array pairs has been declared globally earlier, which is true insofar as it was initialized but I don't know how to pass it into a function without this happening. This is the original array's declaration:
pair pairs[MAX * (MAX - 1) / 2];
Thanks!
Just try to change the names of these variables sent as parameters. I think it will work. Please do change the name of pairs to pairs_g.
It should not be a problem for many compilers but may be your compiler do not allow the shadowing variable.
int r_g = pair_count - 1;
int l_g = 0;
Merge_Sort(pairs_g, l_g, r_g);
return;
Related
I am in CS50 week 2 arrays bulbs problem
I have a function to turn ASCII value into 8 bit binary then store value in array the problem is without declaring the size of the array it gives error: Variable-sized object may not be initialized and if I declare the size of the array it gives error: declaration shadows local variable I don't know what to do obviously new to coding any and all help is appreciated here is the code:
#include <cs50.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
char* message = get_string("message:");
int i=0;
int array[7]; //this is what gives declaration shadows local variable also have tried int array[]={0,0,0,0,0,0,0,0};
//without this line I get the variable-sized object may not be initialized down bellow
while (message[i] != '\0')
{
int j= message[i]; // this converts char to ASCII
for ( h=7;h>=0;h--)
{
if (j % 2 == 1)
{
int array[h]=1;// if I don't shadow this when declaring size above I get variable-sized
// object may not be initialized
j=(j/2); // I don't actually know if this will result rounding down the .5 since its an
//int but that's really the least of my worries right now
}
else
{
int array[h]=0; //the point of the code is to print each of the chars in the message to an 8 digit binary
j=(j/2);
}
for ( int y=0;y < 8; y++)
{
printf("%i",array[y]); //I understand that I am shadowing the array but if i change the name of the array to array1 then its a new array and would get error variable sized object may not be initialized
}
printf("\n");
i++;
}
}
printf("\n");
}
so I'm sure there are plenty of problems with this code and that it could be better optimized but all I really care about is how I can declare the size of the array without shadowing local variable. Also I had to rewrite all this code line by line copying what I have in visual studio so there could be an syntax error somewhere here that's not in my actual code this is unfinished even with the array error fixed I will still need to print it as light emoji and not ones and zeros.
This is a declaration of an array of type int (of size 7)
int array[7];
this is the same declaration as above, but with initialization
int array[7] = {0, 1, 2, 3, 4, 5, 6};
Further code can access that array via the identifier array, like this
array[h] = 42;
but if you prefix the above expression with the keyword int (e.g. int array[h] = {42};), that is a new declaration of an array of type int (of size h). Since there already exists a variable with that name, the new declaration 'shadows' the previous one. Therefore the warning from the compiler (to make sure, that you know what you're doing).
I am not very good at C and I am really confused about double array. Below is an outline of a code I have a question about. Main function calls CreateRandConn function and passes it a 2D array filled with 0 as an argument. CreateRandConn function takes a 2D array as a parameter, changes some of the value in 2DArray from 0 to 1 and returns the changed 2DArray back to main. I want to indicate in the function prototype the return type of CreateRandConn function is a 2D array. How do I indicate that? I don't really understand the syntax. Is what I wrote wrong? Is the way I am passing the 2DArray as a parameter in the function header incorrect? If so, how I do write it? I still get confused about the relationship between pointers and double arrays. Can someone explain it with the below code outline? Hopefully someone knows what my question is...
//Function prototype
int ** CreateRandConn(char * RandRoom[7], int my2DArray[7][7], char * room_dir);
//Function
int ** CreateRandConn(char * RandRoom[7], int my2DArray[7][7], char * room_dir)
{
...
return my2DArray;
}
int main()
{
int 2DArray[7][7] = {0};
2DArray = CreateRandConn(RandRoomArray, my2DArray[7][7], room_dir);
return 0;
}
I don't really understand the syntax.
Ok, so let's recap the basics:
One cannot assign to an array variable.
If an array gets passed to a function it "decays" to a pointer to its 1st element.
A multidimensional array is just an array of arrays. So a 2D-array is a 1D-array of 1D-arrays, a 3D-array is a 1D-array of 2D-arrays, a 4D-array is a 1D-array of 3D-arrays, and so on ...
A pointer p to an array of N elements of type T is to be defined as: T (*p)[N]
Now for you example:
You have
int 2DArray[7][7] = ...;
for the sake of clarity of the following explanations I change this to be
int a[5][7] = ...;
So this then is passed to a function. Where the following happens/applies:
Following 1. above, it is not possible to pass an array, as if it were possible one would assign it to the variable inside the function, as arrays cannot be assigned, one cannot pass an array.
Following 2. above, the function would need to define the related variable as "a pointer to the arrays 1st element".
Following 3. above, the a's 1st element is an int [7]
Following 4. above, a pointer to an int[7] will be defined as: int(*)[7].
So the function's relevant variable would look like:
... func(int (*pa)[7])
pa points to the 1st element of a. As a side note: From this pointer a the function cannot derive how many elements a actually "provides", will say: how many valid element after the one a points to will follow, so this needs to be passed to the function as well:
... func(int (*pa)[7], size_t rows)
From the steps so far we learned, that an array is not passed, but just a pointer to it's 1st element *1 is passed, is copied into the function's local variable (pa here).
From this directly follows that an array cannot be passed back as the function's return value, but just a pointer to an array's element (typically the 1st)
Looking at how a pointer to an array is defined: T (*p)[N] we know need to derive how a function returning a pointer to an array would look. The function's defalcation somewhat needs to become the p above. So taking T as int and N as 7 we then get:
int (*func(int (*pa)[7], size_t rows))[7];
The trivial implementation and usage then would be:
#include <stdlib.h> /* for size_t */
#define ROWS (5)
#define COLS (7)
int (*func(int (*pa)[COLS], size_t rows))[COLS];
int (*func(int (*pa)[COLS], size_t rows))[COLS]
{
for (size_t i = 0; i < rows; ++i)
{
for (size_t j = 0; j < COLS; ++j)
{
pa[i][j] = 0;
}
}
return pa;
}
int main(void)
{
int a[ROWS][COLS];
int (*pa)[COLS] = func(a, ROWS);
return EXIT_SUCCESS;
}
*1
(which sloppy, but wrongly spoken often is referred to as "a pointer to an array is passed", which in general it is not, but just here, as it's a 2D-array, will say the array's elements are arrays themselves).
If you understood the above, then just for completeness following a less strange looking (but also probably less educational ;-)) version of the above function declaration. It may be declared by using a typedef construct hiding away the somehow complicated declaration of the array-pointers as parameter and return type.
This
typedef int (*PA)[COLS];
defines a type pointing a an array of COLS of ints.
So using PA we can instead of
int (*func(int (*pa)[COLS], size_t rows))[COLS];
write
PA func(PA pa, size_t rows))[COLS];
This version is identical to the above.
And yes it looks simpler, but brings along the fact, that pointers pa and the function's return value) are not identifiable as being pointers by just looking at their definition. Such constructs are considered "bad practice" by many fellow programmers.
I have an API which will take triple pointer as an input as below.
extern int myAPI(int ***myData);
Internally "myData" is treated as array of pointer to array of pointers.
So now in another function, i need to call this myAPI. But i am not able to build the array of pointer to array of pointers. Can you please someone help?
I tried similar to below snippet of code. But seen type mismatch compilation error.
int i[10];
int j[10];
int *k[10];
int *l[10];
int *(*m[])[2];
int a = 0;
for (a = 0; a < 10; a++) {
k[a] = &(i[a]);
l[a] = &(j[a]);
}
m[0] = k;
m[1] = l;
a = myAPI(m);
So you want an "array 10 of pointer to array of pointer 20 to int" (you have to specify the dimensions for all but functions arguments where you can omit the outermost dimension only).
That would be:
int *(*a[10])[20];
For such constructs, cdecl is very helpful. The line in quotes is the declaration for the tool.
Note this is what you asked for. Which is not necessarily what you really need. Often such complex constructs are a symptom of a severe design flaw. You might want to reconsider your program code.
Try changing the declaration of m to
int **m[2];
I'm still pretty new to coding so I'm having trouble with the syntax in this situation. How am I supposed to format this? Whenever I try to build the program, it says that there is an error:
error: expected primary-expression before ']' token
assign_q(chess[][]);
There's no need for me to put all my code here, but here's a little snippet:
#define N 8
int chess[N][N] = {2}, l, m;
void assign_q(int chess[N][N]);
int main()
{
int i, j;
assign_q(chess[][]);
In C, if you want to pass an array, you just have to do not have to use the []-operator. The []-operator is only for access to array-elements.
In your example chess is already of type int [][], so there is no need to de-reference it.
However, you may not have to pass the array at all. If you declare the array at global scope as you have done it, you can access it directly from anywhere within the same compilation unit or another one by using extern.
regarding this line:
assign_q(chess[][]);
What your trying to do is pass a pointer to the chess array
and in C, when an array name is referenced, it devolves to a pointer to that array;
so this will work.
assign_q(chess);
where assign_q will have a prototype of:
void assign_q( int * chess );
and a declaration of:
void assign_q( int * chess )
{
int row;
int column;
....
}
then access the chess array as:
chess[row][column]
I'm a bit confused at the difference here, in C99:
int myfunc (int array[n], int n) { ... }
will not compile. As far as I know you must always put the reference to the array size first, so it has to be written:
int myfunc (int n, int array[n]) { ... }
But if you supply the static keyword, this works absolutely fine:
int myfunc (int array[static 1], int n) { ... }
This order if far preferable to me, as I'm used to having arrays come first in a function call, but why is this possible?
Edit: Realising that the third example isn't actually a VLA helps...
For reference, this was the piece of code I was looking at that led to the question:
int sum_array(int n, int m, int a[n][m])
{
int i, j, sum = 0;
for (i = 0; i < n; i++)
for (j = 0; j < m; j++)
sum += a[i][j];
return sum;
}
The reason why
int myfunc (int n, int array[n]) { ... }
is valid and
int myfunc (int array[n], int n) { ... }
is not is due to the lexical scoping rules of C. An identifier cannot be used before it has been introduced in the scope. There are a few exceptions to this rule but this one is not one of them.
EDIT: here is the relevant paragraph of the C Standard:
(C99, 6.2.1p7) "Any other identifier has scope that begins just after the completion of its declarator."
This rule also applies to parameters declaration at function prototype scope.
The reason for error has already been explained to you: you have to declare n before you can use it in other declarations.
However, it is worth noting that none of these declarations actually declare variable length arrays, as you seem to believe.
It is true that syntax with [n] was first allowed in C99 and that it is formally a VLA declaration, but nevertheless in the given context all of these declarations declare array as a parameter of int * type, just like it has always been in C89/90. The [n] part is not a hint of any kind. The fact that you can use [n] in this declaration is indeed a side-effect of VLA support, but this is where any relationship with VLA ends. That [n] is simply ignored.
A "hint" declaration requires keyword static inside the []. So, your declaration with [static 1] is equivalent to classic int array[1] declaration (meaning that 1 is ignored and the parameter has type int *) except that it gives the compiler a hint that at least 1 element must exist at the memory location pointed by array.
It's because arrays must be declared with a constant value so you cannot create an array using a variable size and therefore cannot pass an array with a variable size. Also if it is just a single-dimension array you don't need to pass a value in at all, that is the point of passing in the second parameter to tell you the length of your array.
To get this to work properly just write the function header like this:
int myfunc (int myArray[], int n) {...}
The order shouldn't matter, but you cannot have the size of an array you are passing be variable it must be a constant value.
If you are using GCC and are willing to use some of their extensions, you can accomplish what you wish right here:
int myFunc (int len; /* notice the semicolon!! */ int data[len], int len)
{
}
The documentation for this extension (Variable Length Arrays) is here.
Please note that this extension is NOT available in clang for some reason, I'm not quite sure why, though.
EDIT: Derp, scope, of course.
My question is; why do you need to do it at all? You're really getting a pointer anyway (you can't pass arrays to a function in C, they degrade to a pointer, regardless of the function's signature). It helps to let the caller know the expected size of the input, but beyond that it is useless. Since they are already passing the size, just use...
int myfunc(int arr[], size_t size) {
// ...
}
Or
int myfunc(int *arr, size_t size) {
// ...
}