declaring array size shadows a local variable - arrays

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).

Related

Modifying Array Elements from Separate Functions

I know I've seen several very similar questions posted here, but I can't seem to make sense out of them or apply their solutions to my code to get the desired result.
I'm trying to modify an array acting as a stack from my pop() and push() functions. It's apparent that functions can read arrays that you pass to them, but they can't change the values of the actual array that's declared in my main function. So it's more like the function is acting on a kind of copy of the array you give it in main. (correct me if I'm wrong please)
I got tired of changing about 14 lines in my code every time I wanted to try a new pointer trick I found on the internet, so I made a very simple program that I can easily modify until I get the result I want.
#include <stdio.h>
//supposedly changes the 3rd element of the array from 2 to 3
int modifyArray(int *arr[], int len)
{
printf("changing 2 to 3\n");
arr[3] = 3;
return 0;
}
//desired output: 0, 1, 3, 3, 4
//current output: 0, 1, 2, 3, 4,
int main()
{
int arr[5] = { 0, 1, 2, 3, 4 };
modifyArray(arr, 5);
for (int i = 0; i < 5; i++)
{
printf("%d, ", arr[i]);
}
return 0;
}
I've seen a lot of solutions on the internet that use some malloc() function which I don't understand at all (hence I can't seem to get it to compile when I try to use it) and all of the other methods I've tried either won't compile due to incompatible data types or throw a memory access exception.
Any help would appreciated
This may not be a sufficient answer but currently, I don't think you need to use malloc() in main. In your modifyArray() though, understand that you are receiving the address of the starting point of your array. Thus, arr in modifyArray() is a pointer to a pointer (the name of the array).
Try(*arr)[3]=3; instead of your original code. Plus, I think you might already know this but I'll remind you that since array indexes begin with 0, arr[3] refer to the fourth element of the array.
Kudos!
converting comment to answer:
array index always starts from zero, so that way you are over writing the element at pos 3 with same element, so you dont see any change.
do the below changes to your code.
write other number than 3 in modifyArray , arr[3] = 8; and also change int modifyArray(int *arr[], int len) to int modifyArray(int *arr, int len)
It's a little error in your code syntax. While taking parameter in your function you are declaring like int *arr[] but it should be only * or [] there. You should write like int modifyArray( int *arr, int len ) or int modifyArray( int arr[], int len ).
You should be getting a warning while running your code.
I think this should work!

error: declaration shadows a variable in the global scope

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;

max value in array C

I'm getting a compile errors, that I can't really fix. I need to create a program that initializes an in array, then write a biggest function that takes 2 parameters, an array and it's length and returns the index of the largest element in the array. I will then call this function from main. Can anyone tell me what is the problem?
errors:part1.c: part1.c: In function 'main':
part1.c:6:3: warning: implicit declaration of function 'largest'
part1.c:7:23: error: expected expression before ']' token
part1.c: In function 'largest':
part1.c:17:4: warning: statement with no effect
Thanks!
#include <stdio.h>
int main()
{
int myArray[]={1,2,3,4,5,6};
largest(myArray,6);
printf("%d",myArray[]);
return 0;
}
int largest(int array[], int length)
{
length = sizeof(array)/sizeof(array[0]);
int i = 1;
int max = array[0];
for(i; i<length; i++)
{
if(max < array[i])
{
max = array[i];
}
}
return max;
}
ISSUE 1
You use largest() in main() before you define it. Use a prototype, or move the definition above main().
ISSUE 2
In:
length = sizeof(array)/sizeof(array[0]);
You declare length as int length, but assign to it something of type size_t. That caused the error error: 'length' redeclared as different kind of symbol in the original version of your question.
ISSUE 3
In
for(i; i<length; i++)
you do not assign a value to i. Did you mean
for(i=0; i<length; i++)
? Although you did previously assign a value to i, I believe this is causing warning: statement with no effect (though hard to be sure without line numbers in the provided code).
Also, arrays in C are 0-based. You probably want to initialize i to 0 rather than 1.
ISSUE 4
In the line
printf("%d",myArray[]);
you use %d as a formatting specifier, which means that the supplied argument is expected to be an integer value. You supply an array instead.
C compiles your code in one pass. This means that everything should be defined before it is used. Your function largest is defined after its use, therefore once the compiler sees
largest(myArray,6);
it still doesn't know that largest exists!
The solution would be to either move the definition of largest above main, or better, forward declare the function:
#include <stdio.h>
int largest(int array[], int length);
int main()
{
int myArray[]={1,2,3,4,5,6};
largest(myArray,6);
printf("%d",myArray[]);
return 0;
}
int largest(int array[], int length)
{
/* implementation of largest */
}
Also, the sizeof(array) will not give you the number of elements in largest because that information is lost upon function call. You could move that expression up in the function call to compute and pass the length parameter:
largest(myArray,sizeof(myArray)/sizeof(myArray[0]));
This may also be a typo, but you probably meant to store and print the maximum value:
int max = largest(myArray,sizeof(myArray)/sizeof(myArray[0]));
printf("%d\n",max);
Put a declaration of largest() before main() to resolve the implicit declaration warning:
int largest(int array*, int length);
int main()
The error error: expected expression before ']' token is caused by:
printf("%d",myArray[]);
To print the largest value, you need to store the result of largest() or use it as an argument to printf():
printf("%d", largest(myArray, 6));
This is not what you expect:
length = sizeof(array)/sizeof(array[0]);
as arrays decays to pointers when passed as arguments. It is equivalent to:
length = sizeof(int*)/sizeof(int);
Just use the length argument to control the iteration. Recommend make the arguments to largest() const as the function does not modify them.
The warning: statement with no effect is caused by the i; in the for:
for(i; i<length; i++)
change to:
for(; i<length; i++)
or:
for(i = 0; i<length; i++)
or if C99:
for(int i = 0; i<length; i++)
You could also just move the definition of largest() above the definition of main() and it would work.
Many people have pointed out many issues but surprised no one has mentioned this:
int largest(int array[], int length)
{
length = sizeof(array)/sizeof(array[0]);
Nope, sizeof does not do what you appear to think it does here. It does not magically know the size of your allocations, only takes the size of the underlying type. What you have done is equivalent to sizeof(int*)/sizeof(int).
You should trust the length parameter the caller gave you. There's no way to get the actual size of the array using sizeof, only let the caller tell you how big it is.
You have an error and warnings .. the error is clearly more important.
printf("%d",myArray[]);
the %d format specification implies you want to write an int value, this is not the case, and the likely cause of your error.
There are other warnings that deserved your attention, such as not providing a function prototype for your 'largest` function etc, but those are secondary to fixing the error that prevents compilation.
Of course the warnings should also be eliminated, or a conscious decision should be made to ignore them after examining them.

invalid application of 'sizeof' to incomplete type 'int[]' When accessing integer array pointed by a pointer

I'm trying to learn pointer in C and am writing this little integer array pointer exercise,but ran into a invalid application of sizeof to incomplete type int[] problem. Please tell me where did I go wrong and how to solve it. Thank you.
#include <stdio.h>
int intA[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
int intB[];
void int_copy(const int *source, int *destionation, int nbr)
{
int i;
for(i=0;i<nbr;i++)
{
*destionation++ = *source++;
}
}
int main()
{
int *ptrA = intA;
int *ptrB = intB;
int sizeA = sizeof(intA);
int nbrA = sizeof(intA)/sizeof(int);
printf("\n\n");
printf("[Debug]The size of intA is:%d\n", sizeA);
printf("[Debug]That means the number of elements is:%d\n", nbrA);
printf("\n\nThe values of intA are:\n");
int i;
for(i=0;i<nbrA;i++)
{
printf("[%d]->%d\n", i, intA[i]);
}
int_copy(ptrA, ptrB, nbrA);
int sizeB = sizeof(intB);
int nbrB = sizeof(intB)/sizeof(int);
printf("\n\n");
printf("[Debug]The size of intB is:%d\n", sizeB);
printf("[Debug]That means the number of elements is:%d\n", nbrB);
printf("\n\nThe values of intB are:\n");
for(i=0;i<nbrB;i++)
{
printf("[%d]->%d\n", i, *ptrB++);
}
}
# cc -g -o int_copy int_copy.c
int_copy.c: In function 'main':
int_copy.c:36: error: invalid application of 'sizeof' to incomplete type 'int[]'
int_copy.c:37: error: invalid application of 'sizeof' to incomplete type 'int[]'
The strange thing that I observed is when I ran gdb, I monitored that the copy function, int_copy, runs for 9 times which seems to be right, but the print of intB after the copy function only displays one item in that array.
I'm still struggling about pointers now, so please do help me and forgive my ignorance. Thank you very much.
intB is basically a pointer, and sizeof on it will yield the same as sizeof on int, that's why the print appears only once.
intA is an array with a known size, so the sizeof works.
You need to remember that sizeof is not a run-time call, although it may look so syntactically. It's a built-in operator that returns the size of the type in bytes at the compilation time, and at the compilation time intB is a pointer that should later point to a newly allocated array.
You are also in trouble here, because IntB doesn't have a size so int_copy really doesn't work for it. There is nowhere to copy the ints!
When declaring an array, you have to either give the size inside [] or use an initializer with the values, so the compiler can count them and figure out the size itself.
Actually your int intB[]; statement is invalid, which compiler are you using?
Also, beware that arrays and pointers are not really the same. You can however use the array handle in a call to a function that expects a pointer, so you can give intA to your int_copy function without copying it to a pointer. http://www.lysator.liu.se/c/c-faq/c-2.html

Passing pointers of arrays in C

So I have some code that looks like this:
int a[10];
a = arrayGen(a,9);
and the arrayGen function looks like this:
int* arrayGen(int arrAddr[], int maxNum)
{
int counter=0;
while(arrAddr[counter] != '\0') {
arrAddr[counter] = gen(maxNum);
counter++;
}
return arrAddr;
}
Right now the compilier tells me "warning: passing argument 1 of ‘arrayGen’ makes integer from pointer without a cast"
My thinking is that I pass 'a', a pointer to a[0], then since the array is already created I can just fill in values for a[n] until I a[n] == '\0'. I think my error is that arrayGen is written to take in an array, not a pointer to one. If that's true I'm not sure how to proceed, do I write values to addresses until the contents of one address is '\0'?
The basic magic here is this identity in C:
*(a+i) == a[i]
Okay, now I'll make this be readable English.
Here's the issue: An array name isn't an lvalue; it can't be assigned to. So the line you have with
a = arrayGen(...)
is the problem. See this example:
int main() {
int a[10];
a = arrayGen(a,9);
return 0;
}
which gives the compilation error:
gcc -o foo foo.c
foo.c: In function 'main':
foo.c:21: error: incompatible types in assignment
Compilation exited abnormally with code 1 at Sun Feb 1 20:05:37
You need to have a pointer, which is an lvalue, to which to assign the results.
This code, for example:
int main() {
int a[10];
int * ip;
/* a = arrayGen(a,9); */
ip = a ; /* or &a[0] */
ip = arrayGen(ip,9);
return 0;
}
compiles fine:
gcc -o foo foo.c
Compilation finished at Sun Feb 1 20:09:28
Note that because of the identity at top, you can treat ip as an array if you like, as in this code:
int main() {
int a[10];
int * ip;
int ix ;
/* a = arrayGen(a,9); */
ip = a ; /* or &a[0] */
ip = arrayGen(ip,9);
for(ix=0; ix < 9; ix++)
ip[ix] = 42 ;
return 0;
}
Full example code
Just for completeness here's my full example:
int gen(int max){
return 42;
}
int* arrayGen(int arrAddr[], int maxNum)
{
int counter=0;
while(arrAddr[counter] != '\0') {
arrAddr[counter] = gen(maxNum);
counter++;
}
return arrAddr;
}
int main() {
int a[10];
int * ip;
int ix ;
/* a = arrayGen(a,9); */
ip = a ; /* or &a[0] */
ip = arrayGen(ip,9);
for(ix=0; ix < 9; ix++)
ip[ix] = 42 ;
return 0;
}
Why even return arrAddr? Your passing a[10] by reference so the contents of the array will be modified. Unless you need another reference to the array then charlies suggestion is correct.
Hmm, I know your question's been answered, but something else about the code is bugging me. Why are you using the test against '\0' to determine the end of the array? I'm pretty sure that only works with C strings. The code does indeed compile after the fix suggested, but if you loop through your array, I'm curious to see if you're getting the correct values.
I'm not sure what you are trying to do but the assignment of a pointer value to an array is what's bothering the compiler as mentioned by Charlie. I'm curious about checking against the NUL character constant '\0'. Your sample array is uninitialized memory so the comparison in arrayGen isn't going to do what you want it to do.
The parameter list that you are using ends up being identical to:
int* arrayGen(int *arrAddr, int maxNum)
for most purposes. The actual statement in the standard is:
A declaration of a parameter as "array of type" shall be adjusted to "qualified pointer to type", where the type qualifiers (if any) are those specified within the [ and ] of the array type derivation. If the keyword static also appears within the [ and ] of the array type derivation, then for each call to the function, the value of the corresponding actual argument shall provide access to the first element of an array with at least as many elements as specified by the size expression.
If you really want to force the caller to use an array, then use the following syntax:
void accepts_pointer_to_array (int (*ary)[10]) {
int i;
for (i=0; i<10; ++i) {
(*ary)[i] = 0; /* note the funky syntax is necessary */
}
}
void some_caller (void) {
int ary1[10];
int ary2[20];
int *ptr = &ary1[0];
accepts_pointer_to_array(&ary1); /* passing address is necessary */
accepts_pointer_to_array(&ary2); /* fails */
accepts_pointer_to_array(ptr); /* also fails */
}
Your compiler should complain if you call it with anything that isn't a pointer to an array of 10 integers. I can honestly say though that I have never seen this one anywhere outside of various books (The C Book, Expert C Programming)... at least not in C programming. In C++, however, I have had reason to use this syntax in exactly one case:
template <typename T, std::size_t N>
std::size_t array_size (T (&ary)[N]) {
return N;
}
Your mileage may vary though. If you really want to dig into stuff like this, I can't recommend Expert C Programming highly enough. You can also find The C Book online at gbdirect.
Try calling your parameter int* arrAddr, not int arrAddr[]. Although when I think about it, the parameters for the main method are similar yet that works. So not sure about the explanation part.
Edit: Hm all the resources I can find on the internet say it should work. I'm not sure, I've always passed arrays as pointers myself so never had this snag before, so I'm very interested in the solution.
The way your using it arrayGen() doesn't need to return a value. You also need to place '\0' in the last element, it isn't done automatically, or pass the index of the last element to fill.
#jeffD
Passing the index would be the preferred way, as there's no guarantee you won't hit other '\0's before your final one (I certainly was when I tested it).

Resources