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!
Related
I'm new to programming and I don't really understand this question. Can some of you give me examples of what it means. How do I write a function where a is int values and n is the length?
I'm confused...
I'm not sure what your question is, as you haven't provided much information. However, a function in C is defined like this:
return_type function_name( parameter list ) {
body of the function
}
So, for this situation, we could say:
void arrayFunction( int a[], int n){
//do whatever you need to do with the function here
}
This may help you some.
Suppose you have an array of ints, as follows:
int arr[] = {2,3,4,5,6};
You can see that there are 5 elements inside above array arr. You can count them.
But it happens that when you pass the above arr to function, that function has no idea about how many elements arr contains. See below (incorrect) code snippet:
#include <stdio.h>
void display(int arr[]){
}
int main(void) {
int arr[] = {2,3,4,5,6};
display(arr);
return 0;
}
The function named 'display()' has no idea about how many elements arr has
Therefore you you need to pass the extra argument (the extra argument called 'n') to tell that called function about the number of elements inside arr. You need to tell this separately - the length of arr.
Now this becomes - as you said in your question - arr is int values and n is the length
Below is the correct code:
#include <stdio.h>
void display(int a[], int n){
//Now display knows about lenth of elemnts in array 'a'
// Length is 5 in this case
}
int main(void) {
int arr[] = {2,3,4,5,6};
display(arr, 5);
return 0;
}
Now, the function named 'display()' knows the length of array of int. This is the way you write code where you specify your array and its length.
More formally, this is because while passing array, it decays to a pointer and so the need arises to pass its length also alongwith it.
I am currently reading understanding pointers in c, am at the section were the author talks about passing arrays to functions. Out of all the bellow patterns which is best to use and why ? , does it have anything to do with optimisation ?
#include <stdio.h>
void passAsPointerWithSize(int * arr, int size) {
for ( int i = 0; i < size; i++ ) {
printf("%d\n", arr[i]);
}
}
void passAsPointerWithoutSize(int * arr) {
while ( *arr ) {
printf("%d\n", *arr);
arr++;
}
}
void passWithoutPointerWithSize( int arr [] , int size) {
for ( int i = 0; i <= size; i++ ) {
printf("%d\n", arr[i]);
}
}
void passWithoutPointerUsingWhile(int arr []) {
int i = 1;
while ( arr[i] ) {
printf("%d\n", arr[i++]);
}
}
int main() {
int size = 5;
int arr[5] = { 1, 2, 3, 4 , 5};
passAsPointerWithSize(arr, size);
passAsPointerWithoutSize(arr);
passWithoutPointerWithSize(arr, size);
passWithoutPointerUsingWhile(arr);
}
i compiled it with -std=gnu11 -O3
In the context of function parameters, int arr [] is the same as int *arr because when an array is passed as a function argument to a function parameter, it decays into a pointer to its first element.
So the following declaration:
void foo(int * arr, int size);
is equivalent to:
void foo(int arr[], int size);
When it comes to the question whether you need the size parameter, you need it in order to determine the length of the array, unless:
there is a special value stored in the array that act as an indicator for the end of array (the callee would be responsible for checking against this indicator).
the length of the array is already known to the caller.
Otherwise, how could you possibly know how many elements the array contains?
Out of all the bellow patterns which is best to use and why ?
With the points above in mind, the only thing you can always choose is whether to use the int * syntax or the int [] one for the function parameter.
Although both are equivalent (as explained above), some people may argue that using int * could suggest that there is at most one element, whereas int [] could suggest thet there there is at least one element and there could be more than one.
does it have anything to do with optimization ?
No, or at least, not directly, whether you need the size parameter is actually a matter of whether the size of the array is known by the caller or it can be obtained by means of a stored end-of-array indicator.
First see which one is correct! (based on what you posted)
void passAsPointerWithSize(int * arr, int size) {
for ( int i = 0; i < size; i++ ) {
printf("%d\n", arr[i]);
}
}
This is the one not invoking Undefined Behavior.
The ones using while won't stop unless they get an element having value 0. What if the array has no 0's ? Then it will access way beyond the memory (which is the case here). Perhaps this echos back to a time when strings used to be marked with zeros at their end, in any case, it's bad practice.
The other for loop is looping till index<=size accessing array index out of bounds when index = size, again, undefined behavior.
Now back to your question..
The syntax func(int arr[],..) is the same as func(int* arr,...) on the context of passing a 1D-array to a function. Arrays are passed as pointers - it doesn't matter how you specify the signature.
Looping? - it's just a matter of choice.
Typos and other things...
Typos are the <= or the i=1 initialization in one of the functions. did you not want to print the 0-th element? Well i=1 and then you start looping - it missed the 0-th element.
A compiler, when passed an array, deals with a pointer to the first element of the array no matter how you write it so the form doesn't matter
How do I know the size of the array passed?
In any of the cases - when you pass an array to a function as a pointer - there is no way to know the length of the array unless you have some placeholder which marks the end of the array. If that is not the case then you have to obviously somehow know the length of it - which is what you do when you pass a parameter named size in the function.
Readability + Choice + ...
Writing it as arr[] can be used to convey the meaning that it is an array when we will deal with that pointer. You may skim through the code and get an idea about what it is getting as arguments and what it will possibly do. One may argue that a comment can still serve that purpose - that's where choice comes into the picture.
Yeah, some of them won't work (what do you mean by the condition *arr for instance? are you trying to bring back null terminated strings? don't!)
But, actually the fastest one (barring some crazy compiler optimization which I for one have not seen in practice) if you don't care about order is iterating backwards
void passAsPointerWithSize(int *arr, int size) {
for ( int i = size - 1; i > 0; i-- ) {
printf("%d\n", arr[i]);
}
}
That's because it saves a whole CPU clock cycle every loop, since after you reduce i (i--) the answer of comparing to zero (i > 0) is already stored in the registers
So, in my function when I try to return a long, it acts like I'm returning an int. This mostly comes into play when I'm trying to return a long that has more than 10 digits, it will return an int limited to 10 digits.
For example my code is trying to find the greatest number within an array of longs so,
#include<stdio.h>
#include<stdlib.h>
long maximum(long arr[])
{
long i, max;
for(i = 0; i < sizeof(arr); i++)
{
//This sets the initial number to the maximum
if(i == 0)
{
max = arr[0]
}
else if(arr[i] > max)
{
max = arr[i];
}
}
return max;
}
When I do a printf in the array right before the return it prints out the correct long with all its digits, but when I return it and try to use this function to return the long in another function then it will only return an int limited to 10 digits. I feel like there might be something obvious I'm missing but I don't know what it is.
My guess is that you did not explicitely tell the compiler that the signature would return long from your other instanciation unit. Just state somewhere in your other code that the function really is long maximum(long arr[]). Using gcc, you can even use -Wimplicit-function-declaration
You are not posting the code that processes the return value. I assume that's because you're sure that's not where the bug is. So it's quite obvious that this is where the bug is.
Strategy for finding bugs: You start with the assumption that unknown evil forces keep your program from working and start fluffing around (that's your current stage). In that stage, you're not going to find the problem. The second stage is that you realise that you made a mistake and your job is to find where the mistake is. Emphasis is that you made the mistake. Your code is not correct. So look at it under the assumption that your code is wrong. Look at it under the assumption that code where you are 100% sure that it is correct is actually wrong.
If that strategy doesn't work, imagine that the code isn't written by you and therefore bug free, but written by your worst enemy who will finally get fired by your boss if you can find the bug in his code. That will help.
The clou is that a long has a size of 32bit (−2147483647,+2147483647) that means you aren't able to process larger numbers.
Try to use 'long long int' instead!
For the sizeof operator to give the actual size of the array, you need to:
Allocate the array statically
Refer to the array within its scope of declaration
For example:
void func()
{
int arr[10];
int total_size = sizeof(arr);
int num_of_elements = sizeof(arr)/sizeof(*arr);
...
}
An example of when the array is not statically allocated:
void func()
{
int* arr = malloc(sizeof(int)*10);
int total_size = sizeof(arr); // will give you the size of 'int*'
...
}
An example of when the array is not within its scope of declaration:
void func(int arr[]) // same as 'int* arr'
{
int total_size = sizeof(arr); // will give you the size of 'int*'
...
}
Please note that for your specific purpose, you actually need the number of elements in the array and not its total size (as shown in the first example above).
In addition to all of that, sizeof(long) is not necessarily larger than sizeof(int) on every platform, so you might need to use long long instead.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
pointer arithmetic in C for getting a string
I am a newbie in C and I would like to get the elements of an array with a function, I have tried different options, but I still do not get the elements.
My function is:
void getelements(int *a, int cl)
{
int *p;
for (p=&a[0];p<&a[cl];p++)
{
printf("%d\n",*p);
}
}
I know that the solution should work like that, but it only prints the first element and then memory positions. I am calling my function with:
int v={10,12,20,34,45};
getelements(&v,5);
Any help? I need to use arithmetic of pointers.
Thanks
First, Please don't update code to fix bugs while a question is open. It makes most of the current answers meaningless, doesn't grant credit where it is due to the person(s) that solved one or more issues in your prior code, and makes the casual reader looking for a related problem to their own completely confused by both the question and the answers therein. If you want to amend an update do so in addition to the original problem, but if it an entirely different issue, then mark as answered, give credit where it is due, and open a new question with your new code and different problem(s) (ideally, anyway).
As written now, your function is fine. But your real issue is this:
// compile with -Wall -Werror and look at the warning here
int v={10,12,20,34,45}; // <== WRONG
getelements(&v,5); // <== Harmless, but bad form.
This should be like this instead, assuming you want to print all elements in the array:
int v[] = {10,12,20,34,45};
getelements(v, sizeof(v)/sizeof(v[0]));
Note the [] following your array. Without it, the &v was masking what would have been a big-fat warning or error from the compiler that int is being passed as an int *. Furthermore, if you compile your prior code with full warnings treated as errors (-Wall -Werror for gcc) you will get an error like the following on your v declaration line:
main.c:116:15: Excess elements in scalar initializer
In other words, everything past the first element was ignored, and thus your pointer was running off into undefined behavior land. Changing the declaration and invocation to what I have above will address this as well as ensure you don't make that mistake again, since sizeof(v[0]) won't even compile unless v is an array or pointer type. The latter can still cause headaches when you use a pointer rather than an array with such a calculation, but thats something you just have to discipline yourself against doing in C.
try this and let me know if that works.
void getelements(int *a)
{
int *p;
int l=5;
for (p=a;p<a+l;p++)
{
printf("%d\n",*p);
}
}
It's best to pass in the length of the array along with the array itself.
#include <stdlib.h>
#include <stdio.h>
void get_elements(int* values, int length)
{
int i;
for (i = 0; i < length; ++i)
{
printf("%d\n", values[i]);
}
}
int main(int argc, char** argv)
{
int vals[3];
vals[0] = 0;
vals[1] = 1;
vals[2] = 2;
get_elements(vals, 3);
getchar();
return 0;
}
Using the code similar to your original post (before the addition of the array length as a method parameter), you could do the follow (which is a bit convoluted if you ask me).
void get_elements(int* values, int length)
{
int *p;
for (p = &values[0]; p < &values[length]; p++)
{
printf("%d\n", *p);
}
}
Actually you are passing array address in
getelements(&v,5)
in function
getelements()
you are treating it like an array!!!
void getelements(int *a, int cl)
{
int *p;
for (p=a;p<a+cl;p++)
{
printf("%d\n",*p);
}
}
Let me know if you are cleared conceptually!!!
As per my knowledge and seeing your code.you have hardcoded the length of array to 5. I think you can also pass array length as a parameter to function; or you can use this function and see if it gives the desired result
void getelements(int *a)
{
int *p;
int i = 0;
int l=5;
p = a
for (i = 0;i<l;i++)
{
printf("%d\n",*(p + i));
}
}
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